文章目录
一、多态性
理解:对象的多种形态(使用多态的时候对象必须有继承关系)
1、何为对象的多态性?
对象的多态性: 父类的引用可以指向子类对象
Person s = new Student();
2、多态的使用:虚拟方法调用
方法多态 :创建子类对象时,调用的方法为子类重写父类的方法或者继承的方法 也叫做虚拟方法调用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法
总结:编译看左边,运行看右边
3、多态性的使用前提
① 类的继承关系
② 方法的重写(子类重写父类方法)
二、为什么要使用多态性?
看代码
①代码如下(示例):
public class AnimalTest {
public static void main(String[] args) {
//多态
AnimalTest animalTest = new AnimalTest();
animalTest.fun(new Dog());
animalTest.fun(new Cat());
animalTest.method(new Cat());
}
//多态
public void fun(Animal animal) {
animal.eat();
animal.shout();
}
//如果没有多态性,必须创建子类对象
public void fun(Dog dog) {
dog.eat();
dog.shout();
}
public void fun(Cat cat) {
cat.eat();
cat.shout();
}
}
②代码:
//有多态、随便new个对象可以通用 比如调用animalTest.method(new Cat());
public void method(Object obj){
}
③代码:
//多态 jdbc中调用不同的数据库厂商,相当于在父类中定义了数据库连接,我们操作调用时只需要对应不同的数据库厂商
class Driver{
public void doData(Connection conn){//相当于 new MySqlConnection() 的子类
//按照规范操作数据
//conn.createStatement()
//相当于调用的是mysql连接重写的方法
}
}
三、多态不适用于属性
对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
四、虚拟方法调用
重载:早绑定也是静态绑定,对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法。
重写:动态绑定,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,也就是晚绑定或动态绑定
不要犯傻,如果它不是晚绑定,它就不是多态
五、向上、向下转型
有了对象的多态性以后,内存中实际上加载了父类和子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时只能调用父类声明的属性和方法,子类声明的属性方法不能调用
总结:向下转型要能成功,必须new的是子类对象或者间接子类对象(可以使用instanceof 进行类型判断)
1、向上、向下转型:
问题:多态以后,如何调用子类的属性和方法?
使用强制类型转换符
向下转型 :使用强制类型转换符
Animal animal = new Cat();
Cat cat = (Cat) animal;
向上转型:就是多态 ,创建子类对象时指向父类引用或者父类引用指向子类对象
Animal animal = new Cat();
2、类型转换图
强转有风险:ClassCastExcetion类型转换异常
Animal animal = new Cat();
Cat cat = (Cat) animal;
//Exception in thread "main" java.lang.ClassCastException: com.ming.entities.Cat cannot be cast to com.ming.entities.Dog
Dog dog = (Dog) animal;
原因是:动物已经强转为猫,不能将毛转为狗了
3、避免强转出现问题,使用关键字instanceof
Animal animal = new Cat();
//obj instance class obj是引用对象 class是类或者接口
if(animal instanceof Animal){
System.out.println("obj是class的实例对象");
}
//Dog dog = (Dog) animal;
if(animal instanceof Cat){
Cat cat = (Cat) animal;
System.out.println("obj是class的直接子类或者间接子类");
}
ArrayList arrayList = new ArrayList();
if (arrayList instanceof List) {
System.out.println("obj是class接口的实现类");
}