Java基础访问修饰符全解析
一、Java 访问修饰符概述
Java 中的访问修饰符用于控制类、方法、变量和构造函数的可见性和访问权限,主要有四种:public、protected、default(无修饰符)和 private。
Java 的访问修饰符在编程中起着至关重要的作用,它们决定了类、方法、变量和构造函数在不同场景下的可见性和可访问性。以下分别介绍这四种主要的访问修饰符:
1. public 访问修饰符
public 修饰符是访问权限最宽松的修饰符,表示任何类都可以访问被修饰的类或类成员。无论这个类位于哪个包中,public 成员始终对所有其他类可见。
- 类:当一个类被声明为 public 时,任何其他类都可以访问这个类。
- 字段、方法、构造器:声明为 public 的字段、方法或构造器可以被任何类访问,不受包和继承关系的限制。
例如:
// 文件:Animal.java
package com.example;
public class Animal{
public String name;
public void makeSound(){
System.out.println("Animal makes a sound");
}
}
在这个例子中,Animal 类和它的 name 字段以及 makeSound () 方法都被声明为 public,因此任何其他包中的类都可以访问它们。
public 修饰符适用于公共 API 和工具类。当类或方法需要暴露给整个应用程序或多个模块时,public 是理想的选择。比如 Java 中的 Math 类的静态方法通常是 public,因为这些方法是通用工具,需要在多个地方调用。
2. private 访问修饰符
private 修饰符是访问权限最严格的修饰符。使用 private 修饰的成员只能在类内部访问,类的外部(包括其子类)无法访问。
- 类:类不能被声明为 private,Java 不允许使用 private 修饰符来限制类的访问权限。
- 字段、方法、构造器:声明为 private 的字段、方法或构造器仅在声明它们的类内部可见,其他类无权访问。
例如:
// 文件:Person.java
package com.example;
public class Person{
private String ssn;// 社会安全号码 (私密数据)
private void displaySsn(){
System.out.println("SSN: "+ ssn);
}
public void setSsn(String ssn){
this.ssn = ssn;
}
}
在这个例子中,ssn 字段和 displaySsn () 方法都是 private,所以它们只能在 Person 类内部被访问。其他类无法直接读取或修改 ssn,只能通过 setSsn () 这样的 public 方法进行控制。
private 修饰符适用于信息隐藏和确保安全性。当类中的某些数据或实现细节不希望被外部访问或修改时,使用 private 是最佳选择,确保了数据封装。敏感数据如密码、个人信息等应使用 private 修饰符,以防止被意外或恶意篡改。
3. protected 访问修饰符
protected 修饰符允许类的成员在同一包内或继承关系中的子类中访问。与 private 不同的是,protected 使得子类可以访问父类的受保护成员。
- 类:类不能声明为 protected。
- 字段、方法、构造器:声明为 protected 的成员在同一个包内的所有类中可见,此外,子类也可以访问它们。
例如:
// 文件:Animal.java
package com.example;
public class Animal{
protected String species;
protected void displaySpecies(){
System.out.println("Species: "+ species);
}
}
// 文件:Dog.java
package com.example;
public class Dog extends Animal{
public void showSpecies(){
this.species = "Canine";// 访问 protected 成员
this.displaySpecies();// 访问 protected 方法
}
}
在这个例子中,Animal 类的 species 字段和 displaySpecies () 方法是 protected 的,Dog 作为其子类可以访问这些成员。
protected 修饰符适用于继承和扩展。当希望类的某些成员能被子类继承和使用,但不希望被完全公开时,使用 protected 是合适的选择。
4. default(无修饰符,包访问权限)
如果在类或成员声明时未显式指定访问修饰符,则默认为包级访问权限。这种访问权限仅限于同一包内的类,包外的类无法访问它们。
- 类:如果类没有显式声明为 public,它就具有包级访问权限,仅对同一包内的类可见。
- 字段、方法、构造器:默认修饰符允许同包中的类访问这些成员,但包外的类和子类都无法访问。
例如:
// 文件:Animal.java
package com.example;
class Animal{
String name;
void makeSound(){
System.out.println("Animal makes a sound");
}
}
// 文件:Test.java
package com.example;
public class Test{
public static void main(String[] args){
Animal animal = new Animal();
animal.name = "Lion";// 同一包内,访问包级成员
animal.makeSound();
}
}
在这个例子中,Animal 类和它的成员没有访问修饰符,因此只能在 com.example 包内被访问。Test 类可以访问 Animal,但位于其他包中的类将无法访问 Animal。
默认访问权限适用于包内共享。当类或成员只需要在同一个包中共享时,可以使用默认访问权限。
二、四种访问修饰符详解
1. public
- 作用:表示被修饰的类、方法、变量或构造函数可以被任何其他类访问。
public 修饰符是访问权限最宽松的修饰符,无论类位于哪个包中,被 public 修饰的类或类成员始终对所有其他类可见。比如一个被声明为 public 的类,任何其他类都可以访问这个类;声明为 public 的字段、方法或构造器可以被任何类访问,不受包和继承关系的限制。
- 可见性:同一类内可见、同一包内可见、不同包中的子类可见、不同包中的非子类可见。
在同一类内,自然可以访问 public 修饰的成员;在同一包内,其他类也能访问 public 修饰的成员;不同包中的子类和非子类同样可以访问 public 修饰的成员。
2. protected
- 作用:表示被修饰的成员可以被同一包内的类和不同包中的子类访问。
protected 修饰符允许类的成员在同一包内或继承关系中的子类中访问。与 private 不同,protected 使得子类可以访问父类的受保护成员。例如,父类中的 protected 成员在同一包内的所有类中可见,此外,不同包中的子类也可以访问这些成员。
- 可见性:同一类内可见、同一包内可见、不同包中的子类可见、不同包中的非子类不可见。
在同一类内,protected 成员是可见的;在同一包内,所有类都可以访问 protected 成员;不同包中的子类可以访问父类的 protected 成员,但不同包中的非子类无法访问。
3. default(无修饰符)
- 作用:如果不指定任何访问修饰符,则默认为 default,也称为包级私有。
默认情况下,如果在类或成员声明时未显式指定访问修饰符,就具有包级访问权限。这种访问权限仅限于同一包内的类,包外的类无法访问它们。
- 可见性:同一类内可见、同一包内可见、不同包中的子类不可见、不同包中的非子类不可见。
在同一类内,无修饰符的成员可见;在同一包内,其他类可以访问无修饰符的成员;但不同包中的子类和非子类都无法访问这些成员。
4. private
- 作用:表示被修饰的成员只能在它所在的类内访问。
private 修饰符是访问权限最严格的修饰符。使用 private 修饰的成员只能在类内部访问,类的外部(包括其子类)无法访问。
- 可见性:同一类内可见、同一包内不可见、不同包中的子类不可见、不同包中的非子类不可见。
只有在声明它们的类内部,private 修饰的成员才可见,同一包内的其他类、不同包中的子类以及非子类都无法访问。
三、不同访问修饰符的使用场景
1. public
- 适用于需要在多个包中访问的类和实例变量。
-
- 当一个类或方法需要被不同包中的多个类访问时,使用 public 修饰符是最合适的选择。例如在设计一个通用的工具类时,可能希望它能够被整个项目中的任何地方调用,这时就可以将工具类声明为 public。如 CSDN 博客中提到的:“public 是最宽松的访问级别,允许类、方法或变量被任何其他类访问。当你希望一个方法或变量可以被任何地方调用或访问时,应使用 public。”
-
- 如果一个成员声明为 public,则它对其他所有的类和对象都是可见的。在不同包中的非子类和子类都可以访问 public 修饰的成员,具有最广泛的可见性。
- 如果一个成员声明为 public,则它对其他所有的类和对象都是可见的。
-
- public 修饰的类、方法、变量或构造函数在同一类内可见、同一包内可见、不同包中的子类可见、不同包中的非子类可见。这意味着无论在哪个位置,只要能够访问到该类所在的包,就可以访问到被 public 修饰的成员。
2. protected
- 适用于需要在子类中访问的变量和方法。
-
- 在设计类的继承结构时,如果某些变量或方法需要被子类访问,但又不希望被其他包中的非子类访问,那么可以使用 protected 修饰符。CSDN 博客中提到:“当一个变量或方法需要被子类访问但不想让包外的其他类访问时,使用 protected。”
-
- 例如在一个父类中定义了一些受保护的方法,子类可以在不同的包中继承并访问这些方法,实现特定的功能扩展。
- 如果一个成员声明为 protected,则它对它所在的类、它所在的包内的所有类以及它的子类都是可见的。
-
- protected 修饰的成员在同一类内可见、同一包内可见、不同包中的子类可见、不同包中的非子类不可见。这体现了 protected 修饰符在继承关系中的特殊作用,既保证了一定的封装性,又允许子类进行适当的访问和扩展。
3. default(包访问权限)
- 适用于同一个包中的所有类和方法。
-
- 当类或方法只需要在同一个包内共享时,可以使用默认访问权限,即不使用任何修饰符。CSDN 博客中提到:“当一个变量或方法只需要在同一个包内的类之间共享时,可以不使用任何访问修饰符。”
-
- 例如在一个项目中,某些辅助类或方法只在特定的包内使用,不需要对外暴露,这时使用默认访问权限可以避免不必要的访问,提高代码的封装性。
- 如果一个成员没有被定义为 public、protected 或 private,它将具有默认访问权限,即同样包中的所有类和方法都可以访问它。
-
- 默认访问权限的成员在同一类内可见、同一包内可见、不同包中的子类不可见、不同包中的非子类不可见。这种访问权限限制在同一个包内,有助于将实现细节限制在特定的范围内,保持代码的整洁和组织。
4. private
- 适用于需要在本类中使用的变量和方法。
-
- 当类中的某些数据或实现细节不希望被外部访问或修改时,使用 private 修饰符是最佳选择。CSDN 博客中提到:“private 是最严格的访问级别,仅允许同一类内部访问。用于封装类的内部状态,防止外部类直接修改这些状态。”
-
- 例如在一个类中,可能有一些敏感数据或内部实现的方法,只在本类内部使用,不希望被其他类访问,这时就可以使用 private 修饰符进行封装。
- 如果一个成员声名为 private,则它只对当前类内部可见。外部类以及任何继承类都不能访问该成员。
-
- private 修饰的成员仅在同一类内可见,同一包内不可见、不同包中的子类不可见、不同包中的非子类不可见。这种严格的访问限制确保了类的内部实现细节不被外部随意访问,实现了良好的封装。