Java 访问修饰符用来指定变量、数据成员、方法、类或构造器的作用范围。这些修饰符帮助限制和保护数据的访问(或访问级别)。
Java 中有四种不同的访问修饰符:
默认访问修饰符
默认访问修饰符意味着我们没有显式声明类、字段、方法等的访问修饰符。
一个没有声明任何访问控制修饰符的变量或方法对同一个包中的其他类可用。接口中的字段默认是 public static final
的,而接口中的方法默认是 public
的。
示例:默认访问修饰符
变量和方法可以在没有任何修饰符的情况下声明,如下所示:
String version = "1.5.1";
boolean processOrder() {
return true;
}
私有访问修饰符 (private
)
声明为私有的方法、变量和构造器只能在声明它们的类内部被访问。
私有访问修饰符是最严格的访问级别。类和接口不能是私有的。
声明为私有的变量可以通过类中的公共获取方法从类外部获取。
使用私有修饰符是对象封装自身并隐藏数据的主要方式。
示例:私有访问修饰符
示例 1
下面的类使用了私有访问控制:
public class Logger {
private String format;
public String getFormat() {
return this.format;
}
public void setFormat(String format) {
this.format = format;
}
}
在这个例子中,Logger
类的 format
变量是私有的,因此其他类无法直接获取或设置它的值。
为了使这个变量对外界可用,我们定义了两个公共方法:getFormat()
返回 format
的值,setFormat(String)
设置其值。
示例 2
在这个例子中,Logger
类的数据成员和类方法是私有的。我们试图在另一个类 Main
中访问这些类方法。
class Logger {
private String format;
private String getFormat() {
return this.format;
}
private void setFormat(String format) {
this.format = format;
}
}
public class Main {
public static void main(String[] args) {
Logger log = new Logger();
log.setFormat("Text");
System.out.println(log.getFormat());
}
}
输出将会是编译错误,因为方法是私有的,无法从 Main
类中访问。
Main.java:18: error: setFormat(String) has private access in Logger
log.setFormat("Text");
^
Main.java:20: error: getFormat() has private access in Logger
System.out.println(log.getFormat());
^
2 errors
受保护访问修饰符 (protected
)
声明为受保护的变量、方法和构造器只能由同一包内的类或不同包中的子类访问。
受保护的访问修饰符不能应用于类和接口。方法和字段可以声明为受保护的,但是在接口中的方法和字段不能声明为受保护的。
受保护的访问给了子类使用辅助方法或变量的机会,同时防止无关的类尝试使用它。
示例:受保护访问修饰符
示例 1
下面的父类使用了受保护访问控制,以允许其子类覆盖 openSpeaker()
方法:
class AudioPlayer {
protected boolean openSpeaker(Speaker sp) {
}
}
class StreamingAudioPlayer extends AudioPlayer {
boolean openSpeaker(Speaker sp) {
}
}
示例 2
这个例子演示了受保护访问修饰符的使用:
class One {
protected void printOne() {
System.out.println("printOne method of One class.");
}
}
public class Main extends One {
public static void main(String[] args) {
Main obj = new Main();
obj.printOne();
}
}
输出:
printOne method of One class.
公共访问修饰符 (public
)
声明为公共的类、方法、构造器、接口等可以从任何其他类访问。因此,在公共类内部声明的字段、方法、代码块可以从 Java 宇宙中的任何类访问。
但是,如果我们尝试访问的公共类位于不同的包中,则仍然需要导入该公共类。由于类继承,类的所有公共方法和变量都会被其子类继承。
示例:公共访问修饰符
这个例子演示了公共访问修饰符的使用:
class One {
public void printOne() {
System.out.println("printOne method of One class.");
}
}
public class Main {
public static void main(String[] args) {
One obj = new One();
obj.printOne();
}
}
输出:
printOne method of One class.
访问修饰符和继承
对于继承的方法,以下规则适用:
-
在超类中声明为公共的方法在所有子类中也必须是公共的。
-
在超类中声明为受保护的方法在子类中要么是受保护的要么是公共的;它们不能是私有的。
-
声明为私有的方法根本不会被继承,因此它们没有规则。
下表总结了基于访问修饰符的同包/不同包的类中的可访问性:
访问修饰符 |
同一包内 |
不同包内 |
默认 |
可访问 |
不可访问 |
私有 |
不可访问 |
不可访问 |
受保护 |
可访问 |
子类可访问 |
公共 |
可访问 |
可访问 |
示例:继承中的访问修饰符
在这个例子中,我们创建了一个类,其中包含一个私有的变量 age
和一个具有默认作用域的变量 name
。我们使用 setter/getter 方法更新 age
并获取其值,而 name
则直接更新。
public class Puppy {
private int age;
String name;
public Puppy() {
}
public void setAge( int age ) {
this.age = age;
}
public int getAge( ) {
return age;
}
public static void main(String []args) {
Puppy myPuppy = new Puppy();
myPuppy.setAge( 2 );
myPuppy.name = "Tommy";
System.out.println("Age: " + myPuppy.getAge() +", name: " + myPuppy.name );
}
}
输出:
Age: 2, name: Tommy