这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天
✨多态
多态是面向对象程序设计语言一个很重要的特性。上文说到,继承最重要的一个特征就是"is-a"规则。这个规则另一个表述就是“替换原则(substitution principle) ”。这个原则指出,程序中出现超类对象的任何地方都可以使用子类对象替换。
Java中对象变量是多态的。
public class B {}
public class A extends B {} // 继承关系
// 声明变量
A var1 = new A();
B var2 = var1;
// 数组的例子
B[] bArr = new B[10];
bArr[0] = new A();
⚠️Warning: 在 Java 中,子类数组的引用可以转换成超类数组的引用, 而不需要采用强制类型转换。
Super[] s = new Supper[10]; Sub[] sub = s; sub[0] = new Sub(); // 下面的语句就会出现运行时错误 s[0].getSuperAttribute();
多态特点
- 多态对于成员变量而言,还是会优先寻找对应类型的成员
- 多态对于成员方法而言,会优先寻找当前类型中方法表中的类型
class Person {
public String name = "Paul";
public String show() {
sout("Person Name: " + this.name);
}
}
class Student extends Person {
public String name = "Sand";
@Override
public String show() {
sout("Student Name: " + this.name);
}
}
// 伪代码
Person p = new Student();
// p.name: 优先寻找Person的属性,也就是 Paul
// p.show(): 优先寻找 实际类型的方法表 也就是 覆盖的方法
对于成员变量,完全继承了父类的成员变量,子类声明同名的成员变量的时候并不会覆盖父类的成员变量信息,因此成员变量会优先寻找父类的成员变量。
对于成员方法来说比较特殊,虚拟机为了提高性能,子类会生成虚拟方法表,按照类型寻找方法的时候,会直接寻找子类的虚拟方法表进而找到的是子类已经覆盖的方法。
强制类型转换
进行强制类型转换的原因是:要在暂时忽略对象的实际类型之后使用对象的全部功能。
Super s = new Sub();
Sub s = (Sub) s;
强制类型转换注意事项: 在进行强制类型转换之前,先查看是否能成功转换。在Java16中增加了语法糖,详见 if 和 模式匹配。
if (staff[1] instanceof Manager) {
boss = (Manager) staff[1];
// Do something
}
综上所述,
- 只能在继承层次内进行强制类型转换
- 再将超类强制转换成子类之前,需要使用
instanceof进行检查