Java必知---泛型(下)

参考:Java必知—泛型(下)
本文将会讲到的是泛型的进阶知识:通配符、PECS原则和类型擦除。
1.类型通配符

类型通配符:额...说白了就是一个?。

2.PECS原则
PECS全文为“Producer Extends, Consumer Super”,意思是作为作为生产者时使用extends,作为消费者时使用super。 啥玩意儿???听不懂 没关系 来看下面的例子:

List<? extends Ineteger> fe = new ArrayList();		
List<? super Ineteger> fs=new ArrayList();

//The method add(capture#5-of ? extends Object) in the type List<capture#5-of ? extends Object> is not applicable for the arguments (String)
//生产者操作
fe.add(1);
fs.add(1);
//消费者操作
for (Integer s : fe) {
}
for (Integer s : fs) {
}

可以看出,fe.add()作为生产者的动作往集合中添加String类型的数据时,编译器会报错:因为java中不允许不确定的类型加入集合,作为Integer的子类,此时编译器并不知道fe被add进去的具体是什么子类型,因此就会报错(因为子类可能有着和父类不一样的形态,如果不限定规则,随便往里添加各种不同的子类,那在读取list里的内容时,就会出错,因为Java干脆把规则限定在前面)。而在进行消费者的操作时,fs在遍历数据时,由于数据类型为Integer或者Integer的父类,因此,

<?>

因为PECS最大的原则就是无论是生产操作还是消费操作,必须让编译器知道具体操作的类型是什么,否则不好意思,不给过!! 由上面的例子我们可以整理出一下规则:

1.如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)
2.如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)
3.如果既要存又要取,那么就不要使用任何通配符

3.类型擦除:
JDK1.5引入了泛型,旨在减少类型强制转换的操作,加强参数类型的安全,但是泛型的作用域在编译阶段,编译完成之后,所有泛型参数类型都会被清除,这就是类型擦除。 下面来看一段代码:

List<String> listString=new ArrayList();
List<Integer> listInteger=new ArrayList();
	
System.out.println(listString.getClass());
//输出:class java.util.ArrayList
	
System.out.println(listInteger.getClass());
//输出:class java.util.ArrayList
	
System.out.println(listInteger.equals(listString));
//输出:true

上面的代码得出以下结论:listString、listInteger并不是ArrayList的子类,它们都是ArrayList
由此可见,泛型的存在只是在编译阶段,在运行阶段它们的类型已经被擦除,而泛型也不存在父类子类这种说法。

展开阅读全文

没有更多推荐了,返回首页