一. 术语
泛型:声明中具有一个或者多个类型参数的类或者接口,就是泛型;
原生态类型:每一种泛型都定义一个原生态类型(raw type),即不带任何实际类型参数的泛型名称。例如,与List<E>相对应的原生态类型是List。原生态类型就像从类型声明中删除了所有泛型信息一样,他们的存在主要是为了与泛型出现之前的代码相兼容。
二. 理解
从技术的角度来说,像E、List<E>和List<String>这样的类型应称作不可具体化的类型,直观的说,不可具体化的类型是指其运行时表示法包含的信息比它编译时表示法包含的信息更少的类型,唯一可具体化的参数化类型是无限制的通配符类型,如List<?>和Map<?,?>。
泛型只在编译时强化他们的类型信息,并在运行时擦除他们的元素类型信息,其在编译器就会检查泛型类型信息,保证类型安全,一旦通过编译,在运行期一定不会出现类型转换异常,可以擦拭类型信息,从而兼容原生态类型。
使用原生态类型时合法的,但是永远不应该这样做。如果使用原生态类型,就丢失了泛型在安全性和描述性方面的所有优势。
三. Q&A
1. 原生态类型List和参数化的类型List<Object>之间到底有什么区别?
前者逃避了泛型检查,后者则明确告知编译器,他能够持有任意类型的对象。虽然可以将List<String>传递给类型List的参数,但是不能将他传给类型List<Object>的参数。泛型有子类型化的规则,List<String>是原生态类型List的一个子类型,而不是参数化类型List<Object>的子类型,这与泛型的类型安全时一脉相承的,真是因为泛型为了兼容JDK1.5之前的代码,在运行时会进行类型擦除,那么为了让运行时一定不错,故在编译器会做类型检查,保证类型安全性,如果List<String>是List<Object>的子类,那么下面这段代码不在编译报错阻止的话,在运行期一定报错
List<Object> o1 = new ArrayList<String>(); //实际上在这里就不会编译通过
o1.add(new Integer(1));
因此参数化类型是不变的,换句话说,对于任何两个截然不同的类型Type1和Type2而言,List<Type1>既不是List<Type2>的子类型。如果Type2是Type1的子类,List<Type2>是List<? extends Type2>的子类。
2. 无限制通配符类型List<?>和原生态类型List之间有什么区别呢?
通配符类型时安全的,原生态类型则不安全。由于可以将任何元素放进使用原生态类型的集合中,因此很容易破坏该集合的类型约束条件,但是不能将任何元素(除null外)放到List<?>中。