java泛型

继续java基础,由于写博客详细之后太占时间,所以,决定从这篇开始,精简内容,直奔主题。泛型的东西网上资料很多,我在学习中出现过两个问题,依次来讲:

1.Object 与 T

例如Test<Object> 与Test<T>,有何区别,其实最主要的就是一点,防止类型强制转换,虽然说两者都可以放Object的任何子类,但是第一种在取出时需要强转,一方面可能会出错,第二方面,性能不高。后者恰好解决了强制转换的问题。

于是,这里面的大坑出来了,泛型擦除,这是java泛型的最关键概念,其实java的泛型类在编译器编译的时候就进行了擦出,而用最近父类代替。所以,会出现Test<String>.class 与Test<Integer>.class相同。所以,List<Object> 不是List<String> 父类。

2,T与?

例如Test<T extends Object> 与Test<? extends Object> 有何区别,

其实,前者表示是一个固定的类型,就是在使用的时候,都是需要一个固定的类型参数,之后这个对象就一直使用这个类型。

后者则不然,使用的时候,他仍然是个不固定的类型,看个例子

List <? extends Fruit> 意思: List中所有元素都是Fruit的子类(包含本身),
List <? super Fruit> 意思: List中所有元素都是Fruit的父类(包含本身)
1、List <? extends Fruit>
假设:Fruit有子类A、B、C 那么 list.add(A);list.add(B);list.add(C);显然错误(不能存多个类)。
虽然我们现在看的是ABC3个类就会问为什么会把不同类型的存进去,我这样存不就好了。list.add(A);list.add(A);其实这也是错误的,因为在运行之前他可不知道你到底add进去的东西是什么类型,是一样还是不一样,因实例化的时候是 ? 待定。为了避免类型不同的情况,所以会编译不通过。因此java将其设计为不能添加,List<? extends E>不能添加元素,但是由于其中的元素都有一个共性--有共同的父类,因此我们在获取元素时可以将他们统一强制转换为E类型,我们称之为get原则。
2、List <? super Fruit>
假设:Fruit有子类A、B、C 那么 list.add(A);list.add(B);list.add(C); 这却是可以的,为什么呢:
因为他是这么存的:list.add((Fruit)A);list.add((Fruit)B); 自动强转了。因为 小转大是隐性的,大转小才是强转需要加类型。
那这里为什么又不能存Fruit的父类呢? 因为 见假设1,它是?号,类型代表待定,不跑起来他也不知道你到底存的什么。所以我们能手动add()进去的数据都必须是绝对安全的(最低级父类:本身)才能通过。所以直接add父类也是不行的。
由于该集合中的元素都是E的父类型(包括E),其中的元素类型众多,在获取元素时我们无法判断是哪一种类型,故设计成不能获取元素,我们称之为put原则
实际上,我们采用extends,super来扩展泛型的目的是为了弥补例如List<E>只能存放一种特定类型数据的不足,将其扩展为List<? extends E> 使其可以接收E的子类型中的任何一种类型元素,这样使它的使用范围更广。

posted on 2016-07-16 21:00  1204771796  阅读(185)  评论(0编辑  收藏  举报

导航