Java作为一门面向对象的编程语言,通过访问权限修饰符来实现封装特性,合理设置访问权限可以避免外部代码随意修改内部实现,提升代码的健壮性和可维护性。Java提供了四种访问权限修饰符,分别是public、protected、默认(不写修饰符)、private,它们的权限范围从大到小依次排列。

四种访问权限修饰符的权限范围对比
我们可以从四个维度来对比四种修饰符的权限:同类访问、同包不同类访问、不同包子类访问、不同包非子类访问,具体差异如下表所示:
| 修饰符 | 同类 | 同包不同类 | 不同包子类 | 不同包非子类 |
|---|---|---|---|---|
| public | 可访问 | 可访问 | 可访问 | 可访问 |
| protected | 可访问 | 可访问 | 可访问 | 不可访问 |
| 默认(无修饰符) | 可访问 | 可访问 | 不可访问 | 不可访问 |
| private | 可访问 | 不可访问 | 不可访问 | 不可访问 |
各修饰符的具体使用说明
1. public修饰符
public是权限最大的修饰符,被它修饰的类、方法、变量可以被任意位置的代码访问。一般用于对外提供的公共接口,比如工具类的静态方法、需要被外部调用的业务方法等。
示例代码如下,我们定义一个公共类和一个公共方法:
// 公共类,可以被任意包的代码导入使用
public class PublicDemo {
// 公共变量,任意位置都可以访问
public String publicField = "public字段";
// 公共方法,任意位置都可以调用
public void publicMethod() {
System.out.println("这是public修饰的方法");
}
}
2. protected修饰符
protected修饰的成员可以被同类、同包的其他类访问,同时不同包下的子类也可以访问父类的protected成员,但是不同包的非子类无法访问。这个修饰符通常用于父类希望向子类暴露部分实现,但不想完全公开的场景。
下面给出跨包子类的访问示例,首先定义父类的包为com.parent:
package com.parent;
public class Parent {
// protected修饰的变量
protected String protectedField = "protected字段";
// protected修饰的方法
protected void protectedMethod() {
System.out.println("这是protected修饰的方法");
}
}
然后在不同包com.child下定义子类继承Parent:
package com.child;
import com.parent.Parent;
public class Child extends Parent {
public void test() {
// 子类可以直接访问父类的protected成员
System.out.println(protectedField);
protectedMethod();
}
}
3. 默认修饰符(无修饰符)
如果类、方法、变量没有写任何访问权限修饰符,就属于默认访问权限,也叫做包访问权限。只有同类和同包的其他类可以访问,不同包的类(包括子类)都无法访问。这个修饰符适合只在同一个包内部使用的成员,不需要对外暴露。
示例代码如下,定义在com.test包下的类:
package com.test;
// 默认修饰的类,只有同包的类可以导入
class DefaultDemo {
// 默认修饰的变量,同包可以访问
String defaultField = "默认字段";
// 默认修饰的方法,同包可以调用
void defaultMethod() {
System.out.println("这是默认修饰的方法");
}
}
同包下的其他类可以直接访问这些成员:
package com.test;
public class SamePackageTest {
public void test() {
DefaultDemo demo = new DefaultDemo();
// 同包可以访问默认成员
System.out.println(demo.defaultField);
demo.defaultMethod();
}
}
4. private修饰符
private是权限最小的修饰符,被它修饰的成员只能在本类中访问,其他任何类都无法直接访问。这个修饰符是实现封装的核心,通常用于类的内部状态变量,只通过类提供的公共方法来修改和获取,避免外部直接修改内部数据。
示例代码如下:
public class PrivateDemo {
// private修饰的变量,只有本类可以访问
private String privateField = "private字段";
// 对外提供的公共方法获取private变量的值
public String getPrivateField() {
return privateField;
}
// 对外提供的公共方法修改private变量的值
public void setPrivateField(String privateField) {
this.privateField = privateField;
}
private void privateMethod() {
System.out.println("这是private修饰的方法");
}
}
其他类无法直接访问private成员,只能通过类提供的公共方法操作:
public class PrivateTest {
public void test() {
PrivateDemo demo = new PrivateDemo();
// 无法直接访问privateField,只能通过get方法获取
String value = demo.getPrivateField();
// 只能通过set方法修改
demo.setPrivateField("新的值");
}
}
使用场景总结
在实际开发中,我们可以遵循以下原则选择修饰符:
- 需要对外提供公共能力的类、方法、常量,使用
public修饰 - 父类希望子类继承但不需要对外公开的成员,使用
protected修饰 - 只在同一个包内部使用的成员,使用默认修饰符即可
- 类的内部实现细节、不希望被外部访问的变量和方法,使用
private修饰
合理选择访问权限修饰符可以让代码的封装性更好,降低模块之间的耦合度,提升代码的可维护性。