在我深入看泛型的时候发现的一个疑惑,
当你开始更深入的钻研泛型的时,会发现大量的东西初看起来是没有意义的。例如,尽管可以申明ArrayList.class,但是不能申明ArrayList<Integer>.class。请考虑下面情况
public class ErasedTypeEquivalence{
public static void main(String[] args){
Class c1 = new ArrayList<Integer>();
Class c2 = new ArrayLsit<String>();
System.out.println(c1 == c2);
}
}
//输出结果
true
ArrayList<Integer>和ArrayList<String>很容易被认为是不同类型。不同类型在行为方面肯定不同,例如,如果尝试将一个Integer放入ArrayList<String>,得到的行为将失败,与把一个Integer放入ArrayList<Integer>将成功得到的行为完全不同。但是上面的程序将任务他们是相同的类型。
下面这段代码将进一步的解释:
class Frob{}
class Fnorkle{}
class Quark<Q>{}
class Particle<POSTITION,MOMENTUM>{}
public class ErasedTypeEquivalence{
public static void main(String[] args){
List<Frob> list = new ArrayList<Frob>();
Map<Frob,Fnorkle> map = new HashMap<Frob,Fnorkle>();
Quark<Fnorkle> quark = new Quark<Fnorkle>();
Particle<Long,Double> particle = new Particle<Long,Double>();
System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
System.out.println(Arrays.toString(map.getClass().getTypeParameters()));
System.out.println(Arrays.toString(quark.getClass().getTypeParameters()));
System.out.println(Arrays.toString(particle.getClass().getTypeParameters()));
}
}
/*Output*/
[E]
[K,V]
[Q]
[POSITION,MOMENTUM]
根据JDK文档描述,Class.getTypeParameters()将“返回一个TypeVariable对象数组,表示有泛型申明所申明的类型参数.....”,这好像是暗示你可能发现参数类型的信息,但是,正如你从输出中所看到的的,你能够发现的只是用作参数占位符的标识,这并非有用的信息。
在泛型代码内部,无法获得任何有关泛型参数类型的信息。
因此,你可以只掉诸如类型参数标识符和泛型类型边界这类的信息——你却无法知道用来创建某个特定实例的实际的类型参数。
Java泛型是使用擦除来实现的,这以为着当你在使用泛型的时,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象。因此List<String>与List<Integer>在运行时事实上是相同类型。这两种形式都被擦除成它们的“原生”类型。