子类只能安全修改父类中声明为protected或public的属性,private和包私有属性不可访问;禁止字段隐藏,应通过getter/setter方法间接控制;跨包时protected属性仅对子类引用可见;构造器中须用super委托初始化。

子类修改父类属性,关键不在“能不能改”,而在于“怎么改才规范、安全、可维护”。Java 的封装和继承机制对属性访问有明确约束,不能靠强行突破,而要遵循可见性规则和设计意图。
只允许访问声明为 protected 或 public 的属性
子类能直接读写父类属性的前提,是该属性在父类中被显式声明为 protected 或 public:
- ✅ protected String name; —— 子类可在自身方法或构造器中直接赋值:
this.name = "Tom"; - ✅ public int id; —— 同样可直接访问,但不推荐,破坏封装性
- ❌ private String password; —— 子类完全不可见,任何直接访问都会编译失败
- ❌ String code;(默认包私有)—— 若子类与父类不在同一包,也无法访问
禁止“重写”属性,只能通过方法间接控制
Java 中属性不参与多态,不存在“重写属性”这回事。子类中声明同名字段,只是隐藏(hiding)父类字段,不会影响父类逻辑,还容易引发歧义:
- 不要在子类里写
protected String name = "default";来覆盖父类的name - 正确做法是:父类提供
protected字段 + 公共 getter/setter,子类通过方法调用安全修改 - 例如父类定义
protected void setName(String name) { this.name = name; },子类可复用或增强该逻辑
跨包场景下必须守牢引用类型边界
即使属性是 protected,也不能通过父类类型引用去访问——这是编译期强制检查的可见性规则:
立即学习“Java免费学习笔记(深入)”;
- ✅
Child c = new Child(); c.name = "ok";—— 合法,引用类型是子类 - ❌
Parent p = new Child(); p.name = "bad";—— 编译报错,p是父类类型,跨包时不可见 - ❌
new Parent().name = "...";—— 父类实例本身也不暴露protected成员给包外代码
优先使用 super 调用父类初始化逻辑
若需在子类构造器中设置父类状态,应通过 super(...) 显式委托,而非绕过封装直接操作字段:
- 父类构造器中完成字段校验、默认值设定等逻辑,子类继承时自动受益
- 例如:
super(name, validateAge(age));比this.name = name; this.age = age;更可靠 - 避免子类绕过父类约束(如跳过空值检查、范围校验),导致对象处于非法状态


















