目录
1.前提
2.优势与弊端
3.编译与运行
4.向上转型与向下转型
5.instance用法
要注意的是,本文章仅涉及多态中的用法讲述,不涉及基础概念(例如:什么是多态,基本概念是什么),那么,开始今天的主题。
1.前提
继承与重写。
2.优势与弊端
优势:方法中,使用父类型作为参数,可以接收所有子类对象
弊端:不能使用子类特有方法
以代码为例:
public class TestDemo1 {public static void main(String[] args) {Scanner in = new Scanner(System.in);Fu fu = new Zi();System.out.println(fu.name);//输出张三fu.show();//输出我是李四fu.play();//非法,由于paly是子类特有方法,因此编译会报错}
}class Fu{String name = "张三";public void show(){System.out.println("我是张三");}
}class Zi extends Fu{String name = "李四";@Overridepublic void show(){System.out.println("我是李四");}public void play(){System.out.println("王者农药");}
}
3.编译与运行
在多态中,遵循这样一个规则:
调用成员变量时:编译看左边,运行也看左边
调用成员方法时:编译看左边,运行看右边
这里代码部分还以上述为例:
System.out.println(fu.name);//张三
首先,name是成员变量,那么遵循编译看左边,运行也看左边的原则。
编译时要看左边的父类中有没有name这个变量,如果有的话,编译通过,运行时则调用子类的name。
如果父类中没有name,则会报错。
运行时,可以这样理解:
对象是谁就调用谁的变量,对象为fu,所以调用fu的name,就是张三。
fu.show();//我是李四
show是成员方法 ,那么遵循编译看左边,运行看右边的原则。
编译时与上述同理
运行时,可以这样理解:
既然发生了重写,那么在虚方法表中子类的方法会覆盖掉父类的方法,所以调用方法时调用的是子类的show,输出我是李四。
4.向上转型与向下转型
这里由于向上转型就是创建多态,因此不着重讲解
1.向上转型
Fu fu = new Zi();
// 父类型 父类对象 = new 子类型();
这里的fu,只能调用fu与zi中共有的变量,方法。具体如何调用,上述已经讲解。
着重看向下转型
2.向下转型
可以理解为强制类型转换
先以一个代码为例:
int a = 10;double b = 20.0;double c = b+a;System.out.println(c);//30.0int d = a+(int) b;System.out.println(d);//30
为什么要举这个例子呢?我们都知道由低精度转到高精度,可以自动转换。而从高精度转向低精度,则需要强制类型转化。我认为,向上转型与向下转型可以按照这种方法来理解记忆。
先看向下转型的代码:
Fu fu = new Zi();Zi zi = (Zi) fu;zi.play();//王者农药
可以理解为,fu是父类对象,zi为子类对象,若想将父类对象赋给子类对象,就必须通过强制类型转换才可。zi可以调用子类所特有的方法,变量。
还可粗暴点理解,直接将向下转型这一步理解成创建子类对象即可。
要注意的是:
向下转型并不是随意转型,例如:
class Fu{String name = "张三";public void show(){System.out.println("我是张三");}
}class Zi1 extends Fu{String name = "李四";@Overridepublic void show(){System.out.println("我是李四");}public void play(){System.out.println("王者农药");}
}class Zi2 extends Fu{String name = "王五";@Overridepublic void show(){System.out.println("我是王五");}public void play(){System.out.println("吃鸡");}
}public class TestDemo1 {public static void main(String[] args) {Scanner in = new Scanner(System.in);Fu fu = new Zi1();Zi1 zi1 = (Zi1) fu;zi1.play();//王者农药Zi2 zi2 = (Zi1) fu;//会报错,无法转型}
}
为何 Zi2 zi2 = (Zi1) fu; 这一步会报错呢?
因为转换的类型与真实类型不同,所以会报错。
而怎么知道自己转换是否正确呢,那么就要用到instance关键字了。
5.instance用法
instance关键字可用于判断类型转化是否有误
先看代码:
class Person{String name;int age;
}
class Student extends Person{public void study(){System.out.println("学生在学习");}
}class Teacher extends Person{public void teach(){System.out.println("老师在教书");}
}public class TestDemo1 {public static void main(String[] args) {Scanner in = new Scanner(System.in);Person person = new Student();if(person instanceof Student ){Student student = (Student) person;student.study();} else if (person instanceof Teacher) {Teacher teacher = (Teacher) person;teacher.teach();}//输出结果为:学生在学习Person person1 = new Teacher();if(person1 instanceof Student ){Student student = (Student) person1;student.study();} else if (person1 instanceof Teacher) {Teacher teacher = (Teacher) person1;teacher.teach();}//输出结果慰:老师在教书}
}
instance用于判断person以及person1的类型,并在if语句中进行向下转型调用Teacher以及 Student的特有方法。
而像其中先判断类型再创建对象这一步骤比较繁琐,可以进行精简
Person person = new Student();if(person instanceof Student ){Student student = (Student) person;student.study();}//可精简为if(person instanceof Student student){student.study();}//这一步是在进行判断的同时,如果类型匹配,便直接创建对象
关于向下转型的总结:
1.向下转型可以变为真正的子类类型,从而调用子类特有的方法
2.转化类型与真实类型不一样会报错
3.转化时用instance关键字判断