在《Java泛型总结》中已经详细介绍了泛型的相关知识,本文继续来看几个问题。
java泛型的通过对变量进行类型限制,使得在编译阶段尽可能发现更多的错误,因此强化了类型安全,同时消除了许多强制类型转换。为了与JDK5.0之前的版本保持兼容,编译器会把泛型代码首先转换为不带泛型的代码,具体分为以下几步:
1.将参数化类型中的类型参数"擦除"(erasure)掉;
2.将类型变量用"上限(upper bound)"取代,通常情况下这些上限是 Object。这里的类型变量是指实例域,本地方法域,方法参数以及方法返回值中用来标记类型信息的"变量",例如:实例域中的变量声明 A elem;方法声明 Node (A elem){};,其中,A 用来标记 elem 的类型,它就是类型变量。
3.添加类型转换并插入"桥方法"(bridge method),以便覆盖(overridden)可以正常的工作。
下面结合一些具体的问题来分析。
public class Collections {
public static void copy(List super T> dest, List extends T> src) {
for (int i=0; i
List
List
如果说? extends T指定了元素的上界,? super T 则指出了元素的下界。与? extends T不同的是它只能存数据不能取数据(这样说不是特别严格),因为我们只知道它是T的父类,但是同样无法确切的知道它的类型。(? extends T与? super T就好像各自指定了一个区间[null,T]---[T,Object])。
对于泛型有一个存取原则:如果只取数不放数,就用? extends T;如果只放数不取数,则用? super T;如果即取数又放数则用类型参数T。
像是上面代码中的copy函数就是对这个原则最好的诠释。关于copy函数,或许会有这样的疑问,这里可不可以把参数List super T>用List
再看一段代码:
private Map> a =
new HashMap>();
这段代码编译时会报错:不兼容的类型。上面说过泛型的主要目的是对元素类型进行限制,加强类型安全,减少强制转换。这里我们看一下这段代码,为什么会报错呢?假如编译器允许这段代码通过检查,那么,map中第二个元素就不仅可以存放ArrayListList
list.add(new Integer(1));
接着看另外一段代码:
public static List group(E ... numbers) {
return Arrays.asList(numbers);
}
这样使用List最后再看一个来自statckoverflow的提问:
import java.util.*;
public class Test {
public void createA(List> c) {
A a = new A(c);//warning here
}
public void createB(List> c) {
B b = new B(c);//error here: The constructor B(List>) is undefined
}
}
interface I{
}
class B implements I{
public B(List> c){
}
}
class A implements I{
public A(List> c){
}
}
ans:直接贴出回答
public B(List> c) {
}
The ? is the unknown type. It is not a wild card for any other type. The compiler tells the truth, there is no constructor for the type List> (T is not ?)
It doesn't really work for the other method too. You simply exchanged the compile error by a "unchecked conversion" warning. Because class A is parametized, you'd have to call it like that:
public
A
}
And voilà, say hello to the same error.