Java泛型解惑

转载请标注: 披萨大叔的博客 http://blog.csdn.net/qq_27258799/article/details/52335260

初识泛型

关于泛型的使用,我们平时使用最多的可能就是如下场景:

List<String> list = new ArrayList<String>();

<>就是泛型的标志。

不加泛型之前,List这个容器就像一口大锅,你可以往里面丢任何食材。你可以丢一个String、可以丢一个Integer,就像下面:

List l = new ArrayList();
l.add("鱼");
l.add("鸭");
l.add(100);

这都是允许的,因为List集合默认类型是Object。

但是当你取得时候,List集合可不知道你丢进去的是什么类型,所以只能返给你Object,此时你还必须要类型转换,因此只能这么用:

String yu = (String)l.get(0);
String ya = (String)l.get(1);
String bai = (String)l.get(2);//有什么脏东西混进来啦

这时,你忘记List里还有Integer类型的数据了,于是就报了一个java.lang.ClassCastException

显然这样的编码是很危险也很不方便的。俗话说,万物存在即合理。而此时,泛型就显得尤为重要。

List<Sting> guo = new ArrayList<String>();

这段代码的潜台词是:List你不是记不住塞进去的类型嘛,我来告诉你,现在你只能装String类型的数据。这时,你再装别的类型,IDE就会“红色警告”你。

因此我们可以知道,泛型的存在让我们的编码更灵活、简单、高效。
但是 只停留在在会用的基础上,往往在面对一些深层次的问题时,变得不知所措。

下面我们看两道题:
第一道:

  List<String> a = new ArrayList<String>();
  List<Integer> b = new ArrayList<Integer>();
  System.out.println(a.getClass() == b.getClass()); //true

第二道:

class A {}
class B extends A {}
class C extends A {}
class D extends B {}

下面哪一句是正确的 ?
A、The type List<A> is assignable(可转换的) to List.
B、The type List<B> is assignable to List<A>.
C、The type List<Object> is assignable to List<?>.
D、The type List<D> is assignable to List<?extends B>.
E、The type List<?extends A> is assignable to List<A>.
F、The type List<Object> is assignable to any List reference.
G、The type List<?extends B>is assignable to List<?extends A>.

这道题的答案是:ACDG
博主看完以后是懵逼的,至少在没有深入理解泛型时,这些答案我都不理解,没关系,我们会在下边慢慢解析。

深入理解泛型

泛型是编译时技术,在运行时不包含泛型信息,仅仅Class的实例中包含了类型参数的定义信息。泛型是通过java编译器的称为擦除(erasure)的前端处理来实现的。你可以(基本上就是)把它认为是一个从源码到源码的转换,它把泛型版本转换成非泛型版本。

上面这段话有些枯燥、难以理解。大概意思是说,我们定义的泛型,在运行前会被编译器预处理一下,<>内部的信息最后都会被扔掉。即到最后,List<String>List<Integer> 都是被实例化后的 ArrayList 类型,第一道题得以解答。

到此时,我们可以认为:泛型是逻辑上的两种类型,但是实际上是同一种类型。

下面看第二个问题,B是A的子类,那 List< B >是 List< A > 的什么关系?

当然我们现在已经知道答案了,没有关系

下面我们分析一下,假如它们可以互相转换:

List<A> a = new ArrayList<A>();
//……一些插入过程
List<B> b = a;
//……一些插入过程
System.out.println(b.get(0).getClass()); //这里输出什么?

最后输出A还是B,我已傻傻分不清楚。

所以我们要知道:Java代码在编程过程中,顺序不可控,这导致在必要的时候必须要进行类型判断,且进行强制类型转换。显然,这与泛型的理念矛盾,因此,在逻辑上List<A>List<B>没有关系。

泛型指定的元素不具有继承的特性。

而正因此,为了解决泛型中不能像正常Java类中的继承关系,通配符?应运而生。集合可以使用通配符来描述继承关系。

到此为止,再回头看看第二题的答案,应该没问题了吧!

  • 9
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值