向上转型
向上转型(隐式转型,自动转型):把一个子类对象转向为一个父类对象,父类引用指向子类实例
向上转型和动态绑定机制
多态的实现可以借由向上转型和动态绑定机制来完成,其中,向上转型实现了将子类对象向上转型为父类类型;而动态绑定机制能识别出对象转型前的类型,从而自动调用该类的方法,两者相辅相成。在本节中,我们将从多角度总结,向上转型与动态绑定机制的特点和注意事项。
语法:
向上转型
又称为自动转型、隐式转型。即是父类引用指向子类实例,也表示子类的对象可以赋值给父类的对象。向上转型是安全的,因为任何子类都继承并接受了父类的非私有成员方法。
绑定机制
绑定就是将一个方法调用同一个方法所在的类连接到一起。Java中存在静态绑定和动态绑定两种。
其中,静态绑定是指在程序运行之前进行绑定(由编译器和链接程序完成的),也叫做前期绑定。 动态绑定则是指在程序运行期间由 JVM 根据对象的类型自动的判断应该调用哪个方法,也叫做后期绑定。
应用:
- 向上转型
当一个子类对象向上转型父类类型以后,就被当成了父类的对象,所能调用的方法会减少,只能调用子类重写了父类的方法以及父类派生的方法,而不能调用子类独有的方法。
譬如:图(1)所示Pencil继承自Pen,经过图(2)完成向上转型后,图(3)的方法调用会报错:The method show() is undefined for the type Pen,即无法调用不属于Pen的show方法。
(图1)
(图2)
(图3)
绑定机制
静态绑定的示例:
譬如:有一类 Human,它派生出来三个子类 Chinese 类、American 类和 British类,三个子类中都重写了父类中的方法 speak( ):void。
如下图所示,在测试类中用静态绑定的方式调用方法 speak( )。这种调用方式是在代码里指定的,编译时编译器就知道 c 调用的是 Chinese 的 speak( ),a 调用的是 American 的 speak( )。
动态绑定的示例:
如果此时我们在测试类中做以下改动:Human 类中随机生成 Chinese 类、American 类和 British 类的对象,则编译器将不能根据代码直接确定调用哪个类中的 speak( )方法,直到运行时才能根据产生的随机数 n 的 值来确定 human[i]到底代表哪一个子类的对象,这样才能最终确定调用的是哪个类中的 speak( )方法,这就是动态绑定。
向下转型
向下转型也交强制类型转换
向下转型:子类引用指向父类对象,必须进行强转,可以调用子类特有的方法
instanceof运算符
关于类型转换的应用问题
1、向上转型的有什么用处?直接创建子类对象不是更方便?
向上转型的语法:父类类型 父类引用 = new 子类类型(参数);
即:使用父类引用指向子类实例化对象,也称为自动转型或隐式转型。
此时,该引用只能访问子类继承或重写父类的方法,而不能直接访问子类特有的方法。向上转型多适用于,有多个同父子类共同应用的场景,此时,可以借由父类引用,根据实际需要,转型为特定的子类对象实现多态。
譬如:父类Person,有3个子类Chinese、French、Russian,类中分别重写了eat方法
此时,在测试类中,如果需设置方法实现对各子类eat方法的调用。
方案1:创建eatTest方法,设置参数为父类类型,利用向上转型,在main方法中调用时,分别直接传入子类即可。
运行结果:
方案2:分别设置3个eatTest的重载方法,分别设置参数为:Chinese、French、Russian,main方法不变,运行结果也与方案1相同。
由此可清晰看出,采用向上转型设置的方案更加简单灵活。如后续再新增加新的子类,也无需新增eatTest方法,非常方便。
2、为什么需要向下转型,直接实例化子类不是更简单?
向下转型一般是为了重新获得因为向上转型而丢失的子类特性而存在,因此,通常在向下转型前需要先进行向上转型,向下转型通常也会结合instanceof一起应用。
譬如:修改上一问题中的3个子类Chinese、French、Russian,类中分别新增各自独有的方法。
此时如需在测试类eatTest方法中,修改eatTest ,实现针对传入不同的参数分别调用各自独立方法,则可以参考如下代码
由此可见,借由向下转型,可以在灵活应用多态的基础上,同时兼顾子类的独有性,相较于直接创建子类实例,提高了代码加灵活性。
关于向下转型易出现错误总结
1、向下转型需在满足向上转型前提下进行
譬如:如下图所示代码中,父类Person及两个子类Chinese,French,子类中既有重写父类的方法,又有各自独立的方法。
测试类中:先经过向上转型设置one指向Chinese,后由French强转one,此时虽然编译不会报错,但会产生运行时异常。
因此:请注意,向下转型时,不允许转为非原始类型,即“哪来回哪去”
2、类型转换时的括号应用
接上面父类Person及两个子类Chinese,French代码,此时测试类中,先经过向上转型设置on