protected成员一定被子类继承,但访问受限:同一包内任意类可访问,不同包中仅子类自身代码可访问;子类中可直接调用protected方法或读写字段,无需super前缀。

Java 中的 protected 关键字用于控制成员(字段、方法、构造器)的访问范围,它在继承场景中起着关键作用:既保障封装性,又支持子类复用。它的核心规则不是“能不能被继承”,而是“能不能被访问”——protected 成员一定会被子类继承,但能否在子类中直接使用,取决于包关系。
protected 的访问规则很明确
一个被 protected 修饰的成员,在以下两种情况下可被访问:
- 同一包内的任意类(不管是不是子类)
- 不同包中的子类(仅限子类自身代码中,通过
super或直接调用)
注意:不同包中的非子类类,即使拿到子类对象,也无法直接访问父类的 protected 成员——编译会报错。
子类中访问 protected 成员的写法
只要子类继承了含 protected 成员的父类,就可以在子类内部像访问自己的成员一样使用它:
立即学习“Java免费学习笔记(深入)”;
- 直接读写
protected字段(如num = 100;) - 直接调用
protected方法(如printInfo();) - 在构造器或任意实例方法中使用,无需
super.前缀(除非存在同名字段需要区分)
示例:
父类(com.example.Animal):protected void breathe() { System.out.println("Breathing..."); }
子类(com.pet.Dog,不同包):public void run() { breathe(); // ✅ 合法,子类可直接调用 }
常见误区与注意事项
初学者容易混淆的几个点:
-
private 成员不会被子类访问到,但依然被继承——只是不可见、不可用;想让子类能用,就该改用
protected -
protected不等于 “只给子类用”:同一包里的非子类也能访问,这是它和private protected(C#)或 Kotlin 的protected的重要区别 - 子类不能降低父类
protected成员的可见性——比如在子类中重写一个protected方法时,不能把它改成private - 如果父类和子类在同一个包里,
protected的行为和default(包访问)几乎一致;真正体现差异的是跨包继承场景
什么时候该用 protected 而不是 public 或 private
设计意图决定修饰符选择:
- 用
private:纯内部实现细节,连子类都不应依赖(如缓存变量、临时计算逻辑) - 用
protected:有意留给子类扩展或定制的功能,比如模板方法模式中的钩子方法、通用状态字段、供子类复写的工具方法 - 用
public:明确对外暴露的 API,任何使用者都可调用(如toString()、save())
典型例子:父类定义 protected String name; 和 protected void init(),子类可自由读写 name 并按需重写 init(),而外部代码只能通过 public 的 getter/setter 或行为方法间接操作。


















