阿勒泰地区网站建设_网站建设公司_Figma_seo优化
2026/1/15 4:38:12 网站建设 项目流程

Java 多态 (Polymorphism)

多态是面向对象三大特性中最核心、最灵活的特性。它意味着“同一行为,多种实现”

一、多态的基本概念

  • 定义:同一种类型的对象(或引用),在不同的情况下表现出不同的行为和状态。

  • 核心表现形式(向上转型):

    java

    父类类型 引用名 = new 子类对象();

    例如

    java

    Animal a = new Dog(); // 多态 Animal b = new Cat(); // 多态

    这里的Animal是编译时类型,而DogCat是运行时类型。

  • 多态的前提条件(三者缺一不可)

    1. 有继承关系实现关系(接口)。

    2. 有父类(或接口)引用指向子类对象(即向上转型)。

    3. 有方法的重写(否则多态调用方法没有实际意义)。

二、多态的优势

  1. 降低耦合度,提高扩展性:方法参数或容器(如集合)使用父类类型,可以接受任何子类对象,代码通用性更强。

  2. 便于维护:当需要新增一种子类时,无需修改使用父类引用的代码。

  3. 代码简洁:统一的接口,不同的实现。

示例:体现扩展性的优势

java

class Animal { public void eat() { System.out.println("动物吃东西"); } } class Dog extends Animal { @Override public void eat() { System.out.println("狗吃骨头"); } } class Cat extends Animal { @Override public void eat() { System.out.println("猫吃鱼"); } } // 饲养员类 - 核心优势体现 class Keeper { // 参数使用父类类型,可以接收任何Animal子类对象 public void feedAnimal(Animal a) { a.eat(); // 运行时执行具体子类的eat方法 } } public class Main { public static void main(String[] args) { Keeper keeper = new Keeper(); Animal dog = new Dog(); Animal cat = new Cat(); keeper.feedAnimal(dog); // 输出:狗吃骨头 keeper.feedAnimal(cat); // 输出:猫吃鱼 // 未来新增一个Tiger类,Keeper类完全无需修改! // keeper.feedAnimal(new Tiger()); } }

三、多态调用成员的特点(记忆口诀)

这是理解多态行为的关键:

成员类型编译阶段(看左边)运行阶段(看右边)说明
成员变量检查父类中是否有该变量访问父类中的该变量编译和运行都看左边(父类)
成员方法检查父类中是否有该方法声明执行子类中重写后的该方法编译看左边,运行看右边(子类)

示例

java

class Fu { int num = 10; public void show() { System.out.println("Fu show"); } } class Zi extends Fu { int num = 20; @Override public void show() { System.out.println("Zi show"); } public void special() { System.out.println("Zi special"); } } public class Test { public static void main(String[] args) { Fu obj = new Zi(); // 多态 // 访问成员变量:看左边(Fu) System.out.println(obj.num); // 输出:10 // 调用成员方法:编译看左边(Fu),运行看右边(Zi) obj.show(); // 输出:Zi show // obj.special(); // 编译错误!因为编译看左边,Fu类中没有special方法声明 } }

四、多态的弊端与解决方案:类型转换

弊端:在多态的形式下(父类引用),不能调用子类特有的方法或访问子类特有的变量

解决方案:使用引用数据类型转换

1. 向上转型 (Upcasting)
  • 自动进行:子类类型转换为父类类型。

  • Animal a = new Dog();// 安全,因为狗一定是动物。

2. 向下转型 (Downcasting)
  • 强制进行:父类类型转换为子类类型。

  • 语法子类类型 引用名 = (子类类型) 父类引用;

  • 目的:为了“还原”对象的真实子类类型,以便调用子类特有的功能。

示例

java

Animal a = new Dog(); // 向上转型 Dog d = (Dog) a; // 向下转型,将a强制转换为Dog类型 d.lookHome(); // 现在可以调用Dog特有的方法了
3. 转型的风险与安全校验

如果转型的目标类型与对象的真实类型不匹配,会抛出ClassCastException(类型转换异常)。

java

Animal a = new Cat(); Dog d = (Dog) a; // 运行时错误!ClassCastException: Cat cannot be cast to Dog

安全转型:使用instanceof关键字

  • 作用:在转型前进行判断,避免ClassCastException

  • 语法引用变量 instanceof 数据类型

  • 结果:返回boolean值。判断引用指向的对象是否属于该类型(或该类型的子类)。

示例

java

public static void checkAnimal(Animal a) { a.eat(); // 所有动物都有的行为 // 类型判断与安全转型 if (a instanceof Dog) { Dog dog = (Dog) a; dog.lookHome(); } else if (a instanceof Cat) { Cat cat = (Cat) a; cat.catchMouse(); } else { System.out.println("这是其他动物"); } }

五、总结与最佳实践

  1. 多态的本质:通过父类/接口引用调用方法,执行时由JVM根据对象的实际类型决定调用哪个版本的方法(动态绑定)。

  2. 使用场景:当需要编写通用代码、处理一组相关对象、或设计可扩展的系统架构时。

  3. 转型原则

    • 能向上转型就向上转型(利用多态,提高代码通用性)。

    • 必须向下转型时才转(需要使用子类特有功能时)。

    • 向下转型前务必用instanceof判断,确保类型安全。

package polymorphism02; public class Animal { private int age; private String color; public Animal() { } public Animal(int age, String color) { this.age = age; this.color = color; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void eat(String something){ System.out.println("动物在吃东西"); } }
package polymorphism02; public class Cat extends Animal{ public Cat() { } public Cat(int age, String color) { super(age, color); } @Override public void eat(String something){ System.out.println(getAge()+"岁的"+getColor()+"颜色的猫在吃"+something); } public void catchMouse(){ System.out.println("猫抓老鼠"); } }
package polymorphism02; public class Dog extends Animal{ public Dog() { } public Dog(int age, String color) { super(age, color); } @Override public void eat(String something){ System.out.println(getAge()+"岁的"+getColor()+"颜色的狗在吃"+something); } public void lookHome(){ System.out.println("狗在看家"); } }
package polymorphism02; public class Person { private String name; private int age; public Person() { } public Person(int age, String name) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } //饲养狗 /*public void keepPet(Dog dog,String something){ System.out.println("年龄为"+age+"岁的"+name+"养了一只"+dog.getColor()+"颜色的"+dog.getAge()+"岁的狗"); dog.eat(something); } //饲养猫 public void keepPet(Cat cat,String something){ System.out.println("年龄为"+age+"岁的"+name+"养了一只"+cat.getColor()+"颜色的"+cat.getAge()+"岁的猫"); cat.eat(something); }*/ //一个方法能接收使用动物信息 //方法的形参:可以写这些类的父类 public void keepPet(Animal a ,String something){ if (a instanceof Dog d){ System.out.println("年龄为"+age+"岁的"+name+"养了一只"+d.getColor()+"颜色的"+d.getAge()+"岁的狗"); d.eat(something); }else if (a instanceof Cat c){ System.out.println("年龄为"+age+"岁的"+name+"养了一只"+c.getColor()+"颜色的"+c.getAge()+"岁的猫"); c.eat(something); }else { System.out.println("没有这种动物"); } } }
package polymorphism02; public class Test { public static void main(String[] args) { //创建对象并调用 /*Person p = new Person(30, "老王"); Dog d = new Dog(2,"黑"); p.keepPet(d,"骨头"); Person p1 = new Person(26, "老李"); Cat d1 = new Cat(3,"黄"); p1.keepPet(d1,"🐟"); */ Person p = new Person(30, "老王"); Dog d = new Dog(2,"黑"); Cat c = new Cat(3,"黄"); p.keepPet(d,"骨头"); p.keepPet(c,"🐟"); } }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询