您的位置 首页 java

《Java编程思想》基础篇-泛型第四篇-转型

泛型 转型的可行性——数组的转型

《Java编程思想》基础篇-泛型第四篇-转型

声明了几个跟水果相关的类

《Java编程思想》基础篇-泛型第四篇-转型

可以把派生类数组赋值给基类数组——记住这不是向上转型,虽然Java编译期允许,但是确实不是向上转型,如果不相信,我们可以对比泛型集合的向上转型。

泛型转型的可行性——泛型的转型

《Java编程思想》基础篇-泛型第四篇-转型

我们不能把跟Apple相关的泛型转型为跟Fruit相关的泛型。这跟数组的向上转型类似,但是由于集合不是Java的内置类型,并且泛型是通过擦除实现的,编译器无法知道集合所持有的对象的类型,所以不允许这种转型。

从另一种意义来说,Apple的List不是Fruit的List,Apple的数组也不是Fruit的数组。我们现在是在讨论集合或数组的类型,而不是集合或数组持有对象的类型。如果数组不是内置类型,如果数组不知道自己持有对象的类型,那么Apple的数组也是无法向上转型为Fruit的数组。

泛型转型的可行性——数组和泛型转型的总结

千万不要认为派生类数组转型为基类数组是向上转型,是的,大家都这么称呼,但是只要跟泛型的转型进行对比,就会明白,这是向上转型的滥用。

泛型的转型——extends通配符——语法

List<? extends Fruit> flist = new ArrayList<Apple>();

通配符是不能用于声明泛型类和泛型方法的,只能用于声明对象。

泛型的转型——extends通配符——含义

flist的类型是List<? extends Fruit>,表示Fruit子类的list,千万不要认为这个List可以持有任何类型的Fruit。通配符是指向某个确定的Fruit子类。List<? extends Fruit>表示某个Fruit子类的List,具体是哪个子类,没有明确指明。

本来泛型的通配符语法就是为了向上转型而使用的,List<? extends Fruit>表示某个特定的Fruit子类的List,虽然由于转型之后我们不清楚到底是哪个Fruit的子类。

来来,跟数组的向上转型对比一下:

《Java编程思想》基础篇-泛型第四篇-转型

fruit允许插入各种Fruit子类的对象,但是在泛型通配符中,Java不允许插入任何对象,因为泛型的一个目的就是要把运行时检查转移到编译期检查,既然不清楚是哪个Fruit子类,我们怎么能够插入任何Fruit子类的对象呢?

泛型的转型——extends通配符——诡异的地方

《Java编程思想》基础篇-泛型第四篇-转型

泛型向上转型之后什么对象都不能加入List了,但是get得到的对象一定是Fruit类型。

泛型的转型——extends通配符——诡异的地方的解决方案

当你在创建自己的泛型类的时候,记得要处理好通配符的情况:

《Java编程思想》基础篇-泛型第四篇-转型

看清楚,List中的contains和indexOf的参数是Object,如果是参数类型的话,这两个方法就没法调用了。

泛型的转型——super通配符

List<? super Apple> apples

? super Apple表示Apple的任意父类。

泛型的转型——super通配符和extends通配符的比较

List<? super Apple> apples是持有Apple任意父类类型对象的List;

List<? extends Apple> apples是持有Apple任意子类类型对象的List;

文章来源:智云一二三科技

文章标题:《Java编程思想》基础篇-泛型第四篇-转型

文章地址:https://www.zhihuclub.com/172127.shtml

关于作者: 智云科技

热门文章

网站地图