Java中方法支持运行时多态(动态绑定),字段不支持多态(静态解析);同名方法重写由实际对象类型决定,同名字段隐藏由引用声明类型决定;重载是编译时多态,覆盖是运行时多态。

Java 中多态对同名字段和同名方法的处理方式完全不同:方法支持多态(体现为运行时动态绑定),而字段不支持多态(仅按引用类型静态解析)。
同名方法:运行时动态绑定,体现多态
当子类重写(override)父类方法时,调用哪个版本的方法,取决于实际对象的运行时类型,而非引用变量的声明类型。
- 重写要求方法名、参数列表、返回类型完全一致,且访问权限不能更严格
- 子类方法不能抛出比父类更宽泛的检查异常
- 即使通过父类引用调用,JVM 也会在运行时查找到子类对象的真实方法并执行
例如:Father f = new Son(); f.a(); 执行的是 Son.a(),不是 Father.a()。
同名字段:无多态,按引用类型静态解析
字段(成员变量)不存在重写,只有“隐藏”(hiding)。访问哪个字段,完全由引用变量的声明类型决定,编译期就确定了。
立即学习“Java免费学习笔记(深入)”;
-
Father f = new Son(); System.out.println(f.i);输出1(父类字段) - 即使子类定义了同名字段
public int i = 5;,它也不会覆盖父类字段,只是独立存在 - 要访问子类字段,必须使用子类类型引用:
Son s = new Son(); System.out.println(s.i);→ 输出5
重载 vs 覆盖:别混淆同名但不同义的情况
同一类中多个同名方法,靠参数列表区分——这是重载(overload),属于编译时多态;而父子类间同名同参方法,是覆盖(override),属于运行时多态。
- 重载发生在编译期,看的是调用处传入的实参类型和个数
- 覆盖发生在运行期,看的是对象实际所属的类
- 字段既不重载也不覆盖,只按声明类型就近取值
安全访问子类特有成员的建议
若需调用子类独有方法或访问子类字段,需先确认类型再转型:
- 用
instanceof判断运行时类型:if (f instanceof Son) { Son s = (Son) f; s.c(); } - 避免盲目强转,否则触发
ClassCastException - 设计上优先考虑抽象方法或接口,减少对具体子类字段/方法的依赖


















