Java中的多态就是对象的多态,可以分为两种类型:引用多态和方法多态
一.引用多态
父类的引用可以指向本类对象
父类的引用可以指向子类的对象
让我们用代码来解释,先创建一个父类Animal和子类Dog,在主函数中书写如下
但是我们不能把子类的引用直接指向父类的对象,如下:
为什么不能呢?用通俗点的话来解释,我们可以说狗是一种动物,但不能说动物是一种狗,这样就颠倒了属性的从属关系,当父类引用指向子类对象的时候 ,该对象 可以看成是一种特殊的父类。
二.方法多态
上述创建的两个对象,同样都是父类的引用,但是不同的对象可以调用不同的方法,当指向不同的对象时,方法也是多态的。
创建本类对象:调用本类的方法
创建子类对象:调用子类重写或继承的方法。
注意一种特殊的情况:当在子类中编写了一个特殊的方法,没有继承,那此时就不能用通过父类的引用创建的子类对象来调用了。
注意:继承是多态的基础。
三.引用类型转换
了解了多态的含义后,我们在日常使用多态的特性时经常需要进行引用类型转换。
1.向上转型:自动,隐式的转型,是小类型转大类型
还是用之前的例子继续说:
2.向下类型转换:是大类型转小类型,存在风险,可能溢出
将上述代码再加上一行,我们再次将父类转换为子类引用,那么会出现错误,编译器不允许我们直接这么做,虽然我们知道这个父类引用指向的就是子类对象,但是编译器认为这种转换是存在风险的。如:
那么我们该怎么解决这个问题呢,我们可以在animal前加上(Dog)来强制类型转换。如:
有两种出错的情况
①如果父类引用没有指向子类的对象,就向下转型,编译器不会报错但是运行会出错。
②当父类引用已经指向其他子类对象,在通过强制向下转型转换为该子类的对象。
这是因为我们在编译的时候进行了强制类型转换,编译时的类型是我们强制转换的类型,所以编译器不会报错,而当我们运行的时候,程序给animal开辟的是Dog类型的内存空间,这与Cat类型内存空间不匹配,所以无法正常转换。这两种情况出错的本质是一样的,分配内存空间不相同。所以我们在使用强制类型转换的时候要特别注意这两种错误!!下面有个更安全的方式来实现向下类型转换。
3.instanceof运算符
instanceof是Java的一个二元操作符,和==,>,<是同一类东东。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。
我们来使用instanceof运算符来规避上面的错误,代码修改如下:
利用if语句和instanceof运算符来判断两个对象的类型是否一致。
补充说明:在比较一个对象是否和另一个对象属于同一个类实例的时候,我们通常可以采用instanceof和getClass两种方法通过两者是否相等来判断,但是两者在判断上面是有差别的。Instanceof进行类型检查规则是:你属于该类吗?或者你属于该类的派生类吗?而通过getClass获得类型信息采用==来进行检查是否相等的操作是严格的判断,不会存在继承方面的考虑;