Java中使用多态时父类与子类引用创建对象有什么实际差异?
两种写法的差异远不止语法层面,在实际开发中存在非常明确的使用场景区别,核心差异可以从以下几个维度区分:
可调用成员范围不同
用子类类型作为引用时,可以调用子类自己独有的所有属性和方法;但用父类类型作为引用时,哪怕实际运行的对象是子类实例,也只能调用父类中已经定义过的属性和方法,子类独有的成员无法直接访问,必须强制向下转型后才能调用。
举个例子:如果你给spaceship类新增一个独有的调整高度方法public void adjustAltitude(int target),那么:// 子类引用:可直接调用子类独有方法,编译运行正常 spaceship s1 = new spaceship(34.6, "Apollo 11", 1600); s1.adjustAltitude(2000); // 父类引用:直接调用子类独有方法会直接报编译错误 Vehicle s2 = new spaceship(34.6, "Apollo 11", 1600); s2.adjustAltitude(2000); // 编译不通过你当前的测试代码效果一致,是因为你只调用了父类已经定义、子类完成重写的
go()方法,所以看不出调用范围的差异。多态特性的落地必须依赖父类引用(向上转型)
多态的核心价值是统一抽象入口、降低代码耦合,这个特性只有用父类引用才能实现。比如你需要写一个通用的启动交通工具的方法,用父类作为参数类型的话,所有继承自Vehicle的子类都可以通用:// 通用方法,支持所有Vehicle子类,后续新增子类无需修改该方法 public static void startVehicle(Vehicle v) { System.out.println("准备启动交通工具"); v.go(); } // 调用时可以传入任意Vehicle子类实例 startVehicle(new spaceship(34.6, "Apollo 11", 1600)); startVehicle(new car(100.1, "Tesla", "OPEN"));如果你全部用子类作为引用类型,就需要为每个子类单独编写重载方法,代码冗余度会大幅提升,也完全用不到多态的特性优势。
符合面向抽象的工业级编码规范
实际项目开发中普遍遵循「面向抽象编程,而非面向实现编程」的原则,用父类(尤其是抽象类、接口)作为引用类型,可以让代码和具体实现类解耦。后续如果需要替换实现类,比如你原来用的是car类,现在要替换为继承自Vehicle的newEnergyCar类,只需要修改new后的实现类即可,前面的引用类型和后续调用逻辑完全不用改动,代码维护成本会低很多。
内容的提问来源于stack exchange,提问作者Displayname

