Java中为何使用父类引用调用被重写的方法?
哥们儿,这个问题问到点子上了——用父类引用调用被重写的方法,本质上是Java多态特性的核心用法,主要有这几个关键价值:
1. 实现动态多态,让代码适配不同子类场景
这是最核心的原因。Java的动态绑定机制会在运行时根据对象的实际类型(而非引用类型)决定执行哪个方法。就像你给出的示例代码:
class ABC{ public void myMethod(){ System.out.println("Overridden Method"); } } public class XYZ extends ABC{ public void myMethod(){ System.out.println("Overriding Method"); } public static void main(String args[]){ ABC obj = new XYZ(); obj.myMethod(); // 实际执行XYZ的myMethod } }
这里obj是ABC类型的引用,但指向的是XYZ的实例,调用myMethod()时会自动执行子类的重写版本。这种机制让你能写一套通用逻辑,兼容所有继承父类的子类。比如你有一个Shape父类,Circle、Square子类都重写了draw()方法,你可以写一个方法:
public void drawShapes(List<Shape> shapes) { for(Shape shape : shapes) { shape.draw(); // 自动调用对应子类的draw方法 } }
不管你往列表里加Circle还是Square,甚至以后新增Triangle,这个方法都不用改,直接就能正常工作。
2. 提升代码的可扩展性,符合开闭原则
当你需要新增一个子类时,完全不需要修改原来基于父类引用编写的代码。比如上面的Shape例子,新增Triangle类并实现draw()方法后,直接把Triangle对象放进drawShapes方法的参数里,就能自动执行它的draw()逻辑——不需要修改drawShapes的任何代码,完美符合对扩展开放、对修改关闭的设计原则,大大降低了维护成本。
3. 解耦代码,依赖抽象而非具体实现
用父类引用(或者接口引用)编写代码时,你的逻辑依赖的是抽象的父类/接口,而不是具体的子类。这意味着上层代码不需要关心底层到底是哪个子类在工作,只需要和父类定义的方法交互。比如你用List<String> list = new ArrayList<>();,后续对list的操作(add()、get()等)都是基于List接口的方法,哪怕以后把ArrayList换成LinkedList,这些操作代码都不用改,因为它们依赖的是List这个抽象,而非具体的ArrayList实现。这种解耦让代码更稳定、更易维护。
简单来说,这种做法就是Java实现多态的核心手段,能让你的代码更灵活、更易扩展、更易维护——这也是面向对象编程的核心优势之一。
内容的提问来源于stack exchange,提问作者Vijayachandran Chettiar

