一、简介
在 Java 中,多态是面向对象编程中的一个重要概念,它允许不同的对象对同一消息或方法调用做出不同的响应,主要通过方法重写(Override)和方法重载(Overload),以及父类引用指向子类对象来实现。
多态分为动态多态和静态多态。
二、特点
2.1 优点
-
提高代码的可维护性
:由于多态使得相同的方法在不同的对象中有不同的实现,当需要修改某个方法的行为时,只需在相应的子类中进行修改,而不需要在整个代码中查找和修改所有相关的方法调用; -
增强代码的可扩展性
:当需要添加新的子类来扩展功能时,不需要对现有的代码进行大规模的修改,只需要创建新的子类并实现相应的方法; -
促进代码的复用
:通过父类引用可以调用子类对象的方法,减少了重复代码的编写; -
提高代码的灵活性
:可以根据不同的条件动态地选择调用不同子类的方法,使程序更加灵活。
2.2 缺点
由于多态实现的前提必须是继承关系,所以子类只能继承父类已有的方法,也就是说子类只能执行父类已有的方法,而不能执行子类本身独有的方法,可以通过 强制类型装换 来解决,注意要根据多态的实现类提供强制装换后的数据类型。
class Animal {
public void display() {
System.out.println("Animal display() 方法执行了");
}
}
// 子类
class Dog extends Animal {
// 父类的方法
@Override
public void display() {
System.out.println("Dog display() 方法执行了");
}
// 子类的方法
public void eatBone() {
System.out.println("狗吃骨头");
}
}
// 测试类
public class Test {
public static void main(String[] args) {
// 多态的方式创建对象
Animal dogAnimal = new Dog();
// 将父类引用强制转换成子类引用
Dog dog = (Dog) dogAnimal;
// 调用子类独有方法
dog.eatBone();
}
}
运行结果:
狗吃骨头
三、静态多态
静态多态也叫编译时多态 ,通常指的是方法重载(Overload),在编译时就能够确定要调用的具体方法。
public class Main {
public int sum(int a, int b) {
return a + b;
}
public double sum(double a, double b) {
return a + b;
}
public int sum(int a, int b, int c) {
return a + b + c;
}
}
四、动态多态
动态多态也叫运行时多态,通常指的是方法重写(Override),在运行时根据对象的实际类型来决定调用哪个具体的方法实现,通过方法重写和父类引用指向子类对象来实现。
// 父类
class Animal {
public void display() {
System.out.println("Animal,display()方法执行了");
}
}
// 子类
class Dog extends Animal {
@Override
public void display() {
System.out.println("Dog,display()方法执行了");
}
}
// 子类
class Cat extends Animal {
@Override
public void display() {
System.out.println("Cat,display()方法执行了");
}
}
// 测试类
public class Test {
public static void main(String[] args) {
// 创建Dog实现类
Animal myDog = new Dog();
myDog.display();
// 创建Cat实现类
Animal myCat = new Cat();
myCat.display();
}
}
运行结果:
Dog,display()方法执行了
Cat,display()方法执行了
尽管 myDog 和 myCat 的引用类型都是 Animal ,但在运行时,实际执行的 display() 方法分别是 Dog 类和 Cat 类中实现的方法,这就是动态多态的体现。
五、成员的访问方式
在多态中,子类和父类如果有相同的变量和方法,那么该如何执行呢?
// 父类
class Animal {
public final String name = "动物";
public void display() {
System.out.println("Animal,display()方法执行了");
}
}
// 子类
class Dog extends Animal {
private final String name = "狗";
@Override
public void display() {
System.out.println("Dog,display()方法执行了");
}
}
// 测试类
public class Test {
public static void main(String[] args) {
// 多态的方式创建对象
Animal myDog = new Dog();
// 访问成员变量
System.out.println(myDog.name);
// 访问成员方法
myDog.display();
}
}
运行结果:
动物
Cat display()方法执行了
代码解释:
- 访问成员变量:遵循编译看左边,运行也看左边,也就是说他会执行父类的成员变量。
- 访问成员方法:遵循编译看左边,运行看右边,也就是说它会执行子类实现类的方法。