在Java中,当父类引用指向子类对象时,多态通过方法重写(Override)和运行时动态绑定实现,其核心是“编译时检查引用类型,运行时执行实际对象的方法”。以下是具体实现机制和示例说明:
1. 父类引用指向子类对象的基本形式Parent p = new Child(); // 父类引用指向子类对象p.someMethod(); // 实际执行Child类中重写的someMethod()- 编译阶段:编译器检查Parent类中是否定义了someMethod(),确保调用合法。
- 运行阶段:JVM根据实际对象类型(Child)调用重写后的方法。
2. 方法调用的动态绑定机制Java通过虚方法表(vtable)实现动态绑定:
- 子类重写父类方法:调用子类的实现。class Animal { void makeSound() { System.out.println("Animal sound"); } }class Dog extends Animal { @Override void makeSound() { System.out.println("Bark"); } }Animal a = new Dog();a.makeSound(); // 输出"Bark"(执行Dog的实现)
- 子类未重写方法:调用父类的实现。class Animal { void eat() { System.out.println("Eating..."); } }class Dog extends Animal { /* 未重写eat() */ }Animal a = new Dog();a.eat(); // 输出"Eating..."(执行Animal的实现)
- 非多态方法:静态方法、私有方法、final方法不参与重写。class Animal { static void info() { System.out.println("Animal"); } private void secret() {} final void fixedBehavior() {} }class Dog extends Animal { static void info() { System.out.println("Dog"); } // 静态方法隐藏,非重写}Animal a = new Dog();a.info(); // 输出"Animal"(静态方法不表现多态)
3. 属性和静态方法不表现多态- 属性:编译时根据引用类型确定。class Animal { String name = "Animal"; }class Dog extends Animal { String name = "Dog"; }Animal a = new Dog();System.out.println(a.name); // 输出"Animal"(引用类型决定)
- 静态方法:编译时根据引用类型确定,与对象实际类型无关。class Animal { static void print() { System.out.println("Animal"); } }class Dog extends Animal { static void print() { System.out.println("Dog"); } }Animal a = new Dog();a.print(); // 输出"Animal"(静态方法绑定到引用类型)
4. 多态的实际应用场景- 统一处理不同子类对象:List<Animal> animals = new ArrayList<>();animals.add(new Dog());animals.add(new Cat());for (Animal a : animals) { a.makeSound(); // 自动调用Dog或Cat的实现}
- 方法参数使用父类类型:void feedAnimal(Animal a) { a.eat(); } // 可接收任意Animal子类feedAnimal(new Dog());feedAnimal(new Cat());
- 框架扩展:允许用户通过继承和重写扩展功能,无需修改原有代码。
关键总结- 多态三要素:继承、方法重写、父类引用指向子类对象。
- 动态绑定规则:
实例方法:运行时根据实际对象类型调用。
属性/静态方法:编译时根据引用类型确定。
- 优势:提升代码扩展性,实现“开闭原则”(对扩展开放,对修改关闭)。
通过理解“编译看左边(引用类型),运行看右边(实际对象类型)”,可以准确掌握Java多态的核心机制。