方法重写允许子类扩大父类方法访问权限(如protected→public)以保障多态合法性,但字段不能重写只能隐藏,其访问权限不参与多态;应通过重写getter/setter并放宽权限来封装字段访问,确保行为一致与可见可控。

方法重写中允许子类扩大父类方法的访问权限(如 protected → public),本质是为了保障多态调用的合法性与一致性。它不适用于变量(字段),但常被误用于“想让子类字段更可见”的场景——这里需要明确:**字段不能被重写,只能被隐藏;可见性调整必须作用于方法,而非变量本身**。要真正保持子类行为的可见性,关键在于用好重写的方法封装字段访问。
为什么不能靠“放宽变量访问权限”来实现可见性
Java 中字段(成员变量)不存在重写机制:
- 子类定义同名字段,只是隐藏(hiding)父类字段,不是重写;
- 字段的访问权限(
private/protected/默认/public)只影响直接访问,不参与多态分派; - 即使把子类字段设为
public,通过父类引用访问时,仍看到的是父类字段值(见向上转型中的字段绑定规则)。
用重写的方法代替直接暴露字段
把对字段的读写逻辑封装进方法,再在子类中重写这些方法,并按需放宽访问权限:
- 父类用
protected或包级字段 +protectedgetter/setter; - 子类重写 getter/setter,将访问权限升级为
public; - 所有外部访问统一走这些方法,确保行为一致、可见可控。
示例:
父类class Vehicle {<br> protected String brand = "Unknown";<br> protected void start() {<br> System.out.println("Vehicle starting...");<br> }<br> protected String getBrand() { return brand; }<br>}
子类(重写方法并扩大可见性)class Car extends Vehicle {<br> private String model = "Sedan";<br> @Override<br> public void start() { // ✅ 从 protected → public,合法放宽<br> System.out.println("Car engine roaring!");<br> }<br> @Override<br> public String getBrand() { // ✅ 同样可升为 public<br> return "[CAR] " + super.getBrand();<br> }<br> public String getModel() { return model; } // ✅ 新增 public 方法暴露子类特有字段<br>}
这样,无论通过 Car c = new Car() 还是 Vehicle v = new Car() 调用 getBrand() 或 start(),都能获得子类增强后的行为和可见性。
配合向上转型保证行为可见性
当使用父类引用指向子类对象时,只有重写后的方法才能体现子类逻辑:
Vehicle v = new Car();-
v.start();→ 执行Car.start()(因为重写了且是public,可被调用); -
v.getBrand();→ 返回带 “[CAR]” 前缀的字符串; - 但
v.model编译失败(字段不可见),v.getModel()也不行(父类没该方法)——这正说明:**可见性必须由重写的方法提供,而不是字段本身**。
避免常见误区
- ❌ 在子类中把字段改成
public并以为“覆盖了父类可见性”; - ❌ 试图重写
private方法(编译失败,因不可见); - ❌ 忘记加
@Override注解,导致无意中定义了新方法而非重写; - ✅ 正确做法:字段尽量
private,用受控的、可重写的方法暴露行为。

















