多态

1. 什么是多态?

多态:事物的多种形态

2. 多态的表现形式?

  • 父类类型 对象名称 = 子类对象;
  • Fu f = new zi();
  • 把子类对象赋值给父类类型的变量

3. 多态的前提?

  • 有继承/实现关系
  • 有父类引用指向子类对象
  • 有方法的重写(可选的)

4. 多态的好处?

  • 方法中使用父类类型作为参数,可以接收父类对象 + 所有子类对象
  • 如果进行方法重写,利用多态调用方法,可以调用不同子类重写的方法(取决于你在方法中传入的子类对象

5.多态调用成员的特点

  • 变量调用:编译时看左边,运行时看左边 (始终看父类引用类型,不具备多态
  • 方法调用:编译时看左边,运行时看右边(正因为运行时看的是右边的子类对象,所有方法具备多态不同对象执行不同方法,配合上方法重写,执行不同对象的不同方法体,前提是父类中也要有该方法,否则编译会报错。除非你对父类进行强制类型转换,引用类型变成子类后,编译阶段就直接去子类中寻找该方法体,)

变量与方法在调用层面的对比:
成员变量

  • 编译看左边
  • 运行看左边
    → 全程看引用类型,不具备多态

成员方法

  • 编译看左边(在父类中检查方法是否存在)
  • 运行看右边(执行实际对象(右边的子类对象)的方法)
    具备多态

6.因为多态用的是「父类引用」,编译器只认引用的类型,不认实际对象的类型。
编译器编译时:

  • 只知道 animal 是 Animal 类型
  • 不知道它将来会指向 Dog、Cat 还是别的子类
  • 所以它只允许你调用 Animal 类里明确写了的方法
    bark() 是 Dog 独有的,Animal 里没有,编译器直接拒绝。

多态下,成员变量不参与多态,访问谁的变量,完全看引用类型,跟实际对象无关。

class Father {

String name = "父亲";

}

class Son extends Father {

String name = "儿子"; // 子类同名变量

}

多态写法:
Father obj = new Son();
System.out.println(obj.name);

输出结果是:父亲

为什么?
1. 成员变量没有 “重写”,只有 “隐藏”

  • 方法重写:运行时看实际对象
  • 变量:编译时就定死了,看引用类型

Father obj
→ 编译器认为 obj 是 Father
→ 直接访问 Father 的 name
跟你 new 的是 Son 没关系。

结论

  • 方法:多态生效,运行看对象
  • 变量:多态无效,编译看引用

和方法一样:
父类里没有的变量,父类引用根本访问不到。

7.多态的弊端是什么?
不能使用子类特有的功能,因为调用方法的时候,编译看的是左边,如果是子类特有的方法,那么编译时父类找不到方法会报错

8.引用数据类型的类型转换,有几种方式?

  • 自动类型转换(向上转型,把小的变成大的)
  • 强制类型转换(向下转型,把大的变成小的)

9.强制类型转换能解决什么问题?强制类型转换需要注意什么?

  • 可以转换成真正的子类类型,从而调用子类独有功能。
  • 转换类型(父类类型)与真实对象类型(子类类型)不一致会报错
  • 转换的时候用instanceof关键字进行判断

语法:对象 instanceof **类型

1. 类型向下转型前的安全校验
父类引用指向子类对象时,强制向下转型容易类型转换异常,必须先用instanceof判断

Animal animal = new Dog(); // 父类引用指向子类对象

// 安全向下转型
if (animal instanceof Dog) {

Dog dog = (Dog) animal; // 转型不会报错
dog.bark();

2. 多态场景下区分不同子类

同一个父类的多个子类,需要根据实际类型执行不同逻辑。

public void feed(Animal animal) {

if (animal instanceof Dog) {
    System.out.println("喂狗粮");
} else if (animal instanceof Cat) {
    System.out.println("喂猫粮");
}

}
}
作用:基于对象实际类型做分支处理

posted @ 2026-04-23 08:41  AlexXuu  阅读(5)  评论(0)    收藏  举报