list java 泛型_Java泛型:List<?>与List的区别

本文深入探讨了Java中的泛型类型安全和类型擦除概念。List<?> 是类型安全的,因为它限制了对列表元素的读写操作,避免了潜在的ClassCastException。而List的原始类型则允许任意对象的插入,可能导致运行时类型不匹配的问题。通过对比两种类型的使用场景和编译器的行为,解释了为何类型安全和类型擦除对于泛型的重要性。
摘要由CSDN通过智能技术生成

为什么说List>是type-safe而List不是type-safe的?

1、List>

compiler看到了你使用了wildcard ?,那么相当于你对compiler说:“我不知道这个List里面的element的runtime-type是什么,如果我尝试对这个list或者list中取出来的object做一些type-specific的操作,你要给我一个compile-time-error来提醒我”。这样就导致了2个结果:

1.1 list.get()返回类型为?,所以你只能用Object接收,Object足以确保type-safe,因为java中任何class都是Object的subclass。(当然,如果你非要使用类型强制转换,转换成什么阿猫阿狗的class,也没人拦得住你,对此只能说“编译器尽力了,你行你上啊”,反正ClassCastException什么的最有爱了)

2.2 list.put()除了null以外,任何参数都不接收。这也足以确保list中类型的type-safe,要知道,java的泛型的implementation是基于ERASURE(擦除)的,举个具体的例子,LinkedList的内部数据结构肯定是基于Node,那么一个Node有2个field,E element和Node next,而实际上在runtime环境中,LinkedList中的Node并不是Node,仅仅是Node,Node里面的element的类型也不是String,仅仅是Object,也就是说,compile-time的type-information都被抹除了(Quote: For backward-compatibility)。试想这么一个情景,Tom传了一个List给Mike,Mike的interface是List>,Mike往list中放了一个Cat(假设compiler没有阻止Mike),然后Tom取出该List中所有的object并当成Dog使用(compiler会自动加上类型转换的代码——which is how java generics worked),然后Tom就悲剧地得到了一个ClassCastException——这就是为什么除了null其他参数都不接收的原因——阻止Mike随便放东西进去。

2、List

raw-type就是这么个情况,相当于你对compiler说:“我并不在乎这个List里面的element的runtime-type是什么,不管我怎么操作这个list或者list中取出来的object,你都别管,实在看不过去就给我个warning就行了”。这种情况下:

2.1 list.get()返回类型为Object,当然,也是type-safe的(如果你不强制转换的话)

2.2 list.put()的参数类型为Object,也就是说,你爱往里面放什么object就放什么object,还是上面那个例子,就算Tom给Mike的是List,但由于Mike的interface是List,所以Mike放个BigInteger甚至什么Cat、Dog,compiler都不会阻止Mike(但是,要知道,Mike是无法得知其他人会怎么使用这个List的,比如说Mike无法得知Tom相信编译器确保了list中的object都是String,但是由于Mike的raw-type interface,Tom就难免吃ClassCastException咯)

举个具体的例子:

48304ba5e6f9fe08f3fa1abda7d326ab.png

classDog {

public voidbark() {

}

}

classCat {

public voidmeow() {

}

}

public classFoo {

public static void foo1(List> list) { //Java generics are implemented upon ERASURE, so the runtime-type of elements in List> and List are both Object.

if(list.isEmpty()) {

return;

}

Object o = list.get(0); //Type safe if you don't do DOWN-CAST

//list.add(new Dog()); //Won't compile

}

public static voidfoo2(List list) {

if(list.isEmpty()) {

return;

}

Object o = list.get(0); //Type safe if you don't do DOWN-CAST

list.add(new Cat()); //! Compiler won't stop you, just gives you a little complaint

}

public static voidmain(String[] args) {

List cats = new LinkedList();

cats.add(newCat());

List dogs = new LinkedList();

dogs.add(newDog());

foo1(cats); //relatively type-safe

foo2(dogs); //dangerous

for (Cat cat : cats) { //Cast from Object to Cat

cat.meow();

}

for (Dog dog : dogs) { //! Cast from Object to Dog, ClassCastException

dog.bark();

}

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值