文章目录
- 一、多态的概述
- 二、多态中成员访问特点 ★
- 三、多态的优势与劣势
- 四、多态下的类型转换
- 4.2 自动类型转换(从子到父)
- 4.2 强制类型转换(从父到子)
- 4.3 instanceof 关键字
一、多态的概述
多态:是指执行同一个行为,会表现出不同的特征。
常见格式:
多态的前提: 有继承 / 实现关系;有父类引用指向子类对象;有方法重写(多态侧重行为多态)。
二、多态中成员访问特点 ★
-
方法调用:编译看左,运行看右
如下面例子:编译的时候是观察 Animal 对象是否有 run 方法,而运行时调用子类的方法。
-
变量调用:编译看左,运行也看左
如下面例子:编译的时候是观察 Animal 对象是否有 name 变量,并且运行时调用的也是父类的变量。
public abstract class Animal { public String name = "动物"; public abstract void run(); } public class Dog extends Animal{ public String name = "狗狗"; @Override public void run() { System.out.println("狗在跑~~"); } } public class Tortoise extends Animal { public String name = "乌龟"; @Override public void run() { System.out.println("乌龟在跑~~"); } }
public class Test { public static void main(String[] args) { Animal dog = new Dog(); dog.run(); // 狗在跑~~ System.out.println(dog.name); // 动物 Animal tortoise = new Tortoise(); tortoise.run(); // 乌龟在跑~~ System.out.println(tortoise.name); // 动物 } }
注:多态注重行为多态。
三、多态的优势与劣势
在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
Animal a = new Dog();
a.run(); // 后续业务行为随对象而变,后续代码无需修改
定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利。
public class Test {
public static void main(String[] args) {
Animal dog = new Dog();
Animal tortoise = new Tortoise();
run(dog); // 狗在跑~~
run(tortoise); // 乌龟在跑~~
}
public static void run(Animal animal){
animal.run();
}
}
多态下会产生一个问题:多态下不能使用子类的独有功能,因此可利用强制类型转换解决此问题。
四、多态下的类型转换
4.2 自动类型转换(从子到父)
子类对象赋值给父类类型的变量指向。
4.2 强制类型转换(从父到子)
父类类型的变量强制转换为子类对象,格式如下:
作用:可以解决多态下的劣势,可以实现调用子类独有的功能。
注意:如果转型后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现类型转换异常 ClassCastException。
4.3 instanceof 关键字
Java 建议强转前使用 instanceof
判断当前对象的真实类型,再进行强制转换。
判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回 true,反之返回 false。
例1:调用子类独有功能。
public class Animal {
public String name = "动物";
public void run(){
System.out.println("动物可以跑~~");
}
}
public class Dog extends Animal {
public String name = "狗狗";
@Override
public void run() {
System.out.println("狗在跑~~");
}
/**
独有功能
*/
public void lookDoor(){
System.out.println("狗在看门!");
}
}
public class Tortoise extends Animal {
public String name = "乌龟";
@Override
public void run() {
System.out.println("乌龟在跑~~");
}
/**
独有功能
*/
public void layEggs(){
System.out.println("乌龟在下蛋!");
}
}
public class Test1 {
public static void main(String[] args) {
// 自动类型转换
Animal a = new Dog();
a.run();
// a.lookDoor(); // 多态下无法调用子类独有功能
// 强制类型转换:可以实现调用子类独有功能的
// 规定:有继承或者实现关系的 2 个类型就可以强制类型转换,运行时可能出现问题。
// Tortoise t = (Tortoise) a; // 报错。编译阶段可以强制执行不会出错,运行时可能会出错
Dog d = (Dog) a; // 因为 a 可能不是 Dog,可能是 Tortoise,因此需要强转
d.lookDoor();
// 建议强制转换前,先判断变量指向对象的真实类型,再强制类型转换。
if(a instanceof Tortoise){
Tortoise t = (Tortoise) a;
t.layEggs(); // 调用子类独有的功能
}else if(a instanceof Dog){
Dog d1 = (Dog) a;
d1.lookDoor();
}
}
}
例2:多态作为参数的实例。
public class Test2 {
public static void main(String[] args) {
Animal a1 = new Dog();
go(a1);
}
public static void go(Animal a){
System.out.println("预备~~~");
a.run();
// 独有功能
if(a instanceof Tortoise){
Tortoise t = (Tortoise) a;
t.layEggs();
}else if(a instanceof Dog){
Dog d1 = (Dog) a;
d1.lookDoor();
}
System.out.println("结束~~~~");
}
}
文章参考:Java入门基础视频教程,java零基础自学就选黑马程序员Java入门教程(含Java项目和Java真题)