一 引用数据类型之间的转换方式
(1).引用数据类型之间的转换方式有两种:自动类型转换和强制类型转换。
(2).自动类型转换主要指小类型到大类型的转换,也就是子类转为父类,也叫做向上转型。(下面代码红色框中的)
(3).强制类型转换主要指大类型向小类型的转换,也就是父类转为子类,也叫做向下转型或者显式类型转换。(下面代码绿色框中的)
二 关于引用数据类型转换的注意事项(在引用数据类型的转换中常犯的错误)
但是 强制类型转换也是有要求的,并不是什么都能强转,比如说下面的代码:
通过上面的代码错误可以得到:引用数据类型之间的转换必须发生在父子类之间,否则编译报错。强制类型转换要求必须拥有父子类关系。
通过下面的代码得出:没有父子类关系,编译是报错的。但是有了父子类关系,虽然编译不报错,但是运行阶段是不是可能会错的
所以得出结论:若强制的目标类型并不是该引用真正指向的数据类型时则编译通过,运行阶段发生类型转换异常。
其实对上面的对代码Cricle c1=(Cricle)sr;的解释我是有疑问的进一步加深解释
解答:这里的问题是,sr
指向的对象是一个Rect
,而不是一个Circle
。尽管Rect
和Circle
都可能是Shape
的子类,但它们之间并没有继承关系;因为强制类型的转换的前提是相互转换的类型必须是父子类关系。也就是说,一个Rect
对象永远不可能是一个Circle
对象。因此,当你尝试将sr
(一个Rect
对象)转换为Circle
类型时,Java运行时环境会抛出一个ClassCastException
,告诉你不能这样做。
三 如何规避常犯的错误
那我们如何规避上面的错误呢?
官方解决方法:
为了避免上述错误的发生,应该在强转之前进行判断,格式如下:
if(引用变量instanceof数据类型)
判断引用变量指向的对象是否为后面的数据类型
要养成一个良好的习惯,每一次在做强转之前,都做一下判断
具体例子的操作如下:
四 多态的实际意义
疑问:我们自己写好的类类型能不能作为方法的形参类型吗?
问题的具体体现:在这段代码中的体现就是我们自己自定义的类Rect,能否作为类类型来作为我们draw方法的形参类型呢?
解答:
是通过推理的方式得到答案的
对上面的代码进行升级,上面的代码我们总共实现了两个成员方法,一个是打印矩形Rect的行为特征,一个是打印圆Circle的行为特征。我们要求同时打印矩形的特征和圆形的特征,思考如何实现
想法1:就是在成员方法中传入两个形参(就形如绿色框中的那样)
这个想法可行,但是会耦合,当我们在main方法中调用绿色框中的代码时,我们传实参时必须要传入两个实参,但当我们不想要打印任何值时,就还需要给他传入null,在使用上不太方便。我们现在就希望能够达到一种状态就是,就是只用写一个成员方法能够实现下面三个方法实现的内容
解决方法:
打印矩形时,我们用矩形的引用做参数,打印圆形时,我需要圆形的引用做参数,如果说我既要打印矩形,又要打印圆形,这个时候就可以让它们的公共父类作为方法的参数。
此时这样写的好处就在于你无论传递什么子类的对象,哪怕你有更多的子类,都可以通通当做父类图形(Shape)对待,而且我最终打印的结果实际上是不是还可以调用各自重写以后的版本。
总结下来就一句话
多态的实际意义在于屏蔽了不同子类的差异性。你无论是矩形(Rect)还是圆形(Circle),我都屏蔽了你们的差异性,我就实现通用的编程,我都当做父类图形(Shape)对待。但是,由于运行阶段最终调用的都是重写以后不同的show(),所以带来了不同的打印效果。
五 多态的使用场景
场景一:通过形参就是参数的传递,用子类对象给父类的引用进行初始化,形成多态。
解释:(多读几遍就会对这种使用场景有点感觉了,读的过程中一定要结合上面的代码一起)
同一个方法调用可以根据对象的实际类型表现出不同的行为。这里的关键点是,虽然 draw
方法接收的是 Shape
类型的参数,但实际上传递的是 Rect
或 Circle
对象,这叫做“子类对象给父类的引用进行初始化”。通过这种方式,我们可以在不知道具体对象类型的情况下,处理各种不同类型的对象,并让它们各自以适当的方式响应。
场景二:直接在方法体中使用抽象类的引用指向子类类型的对象。
场景三:多态使用场景3:定义方法返回值类型时 定义为父类类型 这样就可以返回任意子类类型的对象
总结:1引用数据类型的转换方式有哪些?
2 在引用数据类型的转换过程中常犯的错误是什么?
3 如何规避常犯的错误?
4 多态的实际意义是什么?
5 多态的使用场景有啥?