Java——权限修饰符
一、权限修饰符的继承访问规则
以下按访问范围从宽到窄排序:
修饰符 | 同包同类 | 同包子类 | 同包非子类 | 跨包子类 | 跨包非子类 |
---|---|---|---|---|---|
public | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
protected | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
默认 (包级) | ✔️ | ✔️ | ✔️ | ❌ | ❌ |
private | ✔️ | ❌ | ❌ | ❌ | ❌ |
关键点:
private
成员:子类无法直接访问,需通过父类提供的public/protected
方法间接操作(如getter/setter
)12。protected
成员:- 允许跨包子类直接访问(如
Child
类继承Parent
类后可直接调用父类protected
方法)。 - 同包内非子类也可访问(如
Test
类与Parent
同包时可直接调用protected
方法)13。
- 允许跨包子类直接访问(如
- 默认(包级):仅允许同包内的子类或非子类访问。
示例:
// 父类(包com.example)
public class Parent {
protected String name; // 跨包子类可访问
String id; // 仅同包子类可访问
private int age; // 子类不可访问
}
// 子类(包com.other)
public class Child extends Parent {
void accessFields() {
name = "Child"; // ✔️ 允许访问protected字段
// id = "123"; // ❌ 跨包无法访问默认权限字段
// age = 10; // ❌ 无法访问private字段
}
}
二、方法重写的权限修饰符规则
子类重写父类方法时,访问权限必须 ≥ 父类方法(保证“里氏替换原则”):
- 父类方法为
public
→ 子类必须为public
。 - 父类方法为
protected
→ 子类可为protected
或public
。 - 父类方法为默认权限 → 子类可为默认、
protected
或public
。 - 禁止缩小权限:如父类方法为
protected
,子类重写时不能改为private
或默认14。
示例:
class Parent {
protected void show() {} // 父类protected方法
}
class Child extends Parent {
@Override
public void show() {} // ✔️ 允许扩大权限(protected → public)
// @Override
// private void show() {} // ❌ 禁止缩小权限(protected → private)
}
三、构造方法与super
关键字的权限限制
- 构造方法继承:
- 子类构造方法默认调用父类无参构造
super()
。 - 若父类无无参构造,子类必须显式调用
super(参数)
,且父类对应构造方法的权限需对子类可见6。
- 子类构造方法默认调用父类无参构造
super
的使用:super
可调用父类的非私有方法或访问非私有字段。super
不能在静态方法(如main
)中使用,因为其依赖于对象实例1。
示例:
class Parent {
protected Parent(int x) {} // 有参构造
}
class Child extends Parent {
public Child() {
super(10); // ✔️ 显式调用父类protected构造方法
}
}
四、官方文档补充
根据Java官方规范:
private
方法:不可被继承,即使子类中出现同名方法,也视为新方法(非重写)7。final
修饰符:若父类方法被声明为final
,子类无法重写该方法7。
五、最佳实践
- 最小权限原则:优先使用
private
,逐步放宽至protected
或public
。 - 继承设计:
- 若父类方法需被子类扩展,使用
protected
。 - 若父类字段需被子类访问但对外隐藏,使用
protected
或提供getter/setter
25。
- 若父类方法需被子类扩展,使用
参考资料:12347