泛型:声明中具有一个或多个类型参数的类或者接口就是泛型
原生态类型的泛型:不带任何实际参数的泛型名称,例如List<E>的原生态类型就是List
使用原生态类型的安全性问题
如果我们在声明泛型的时候使用了原生态类型的泛型,但是最后添加数据的时候却添加了与初始化数据不同的类型的数据,例如这种
List nameList = new ArrayList();
nameList.add(1);
//然后添加
nameList.add("java");
这种错误在编译时并没有什么问题,但是运行时会报错。如上所述,如果不提供类型参数,使用集合类型和其他泛型也任然是合法的,但是不应该这么做。如果使用原生类型,就失掉了泛型在安全性和表述性方面的所有优势。
泛型的子类化
如上所述,虽然不应该在新代码中使用想List这样原生态类型,使用参数化的类型以允许插入任意对象,如List<Object> ,这还是可以的。原生态类型List和参数化类型List<Object>之间到底有什么区别呢?
不严格的说,前者逃避了泛型的检查,后者明确告诉编译器,它能够持有任意类型的对象。虽然你可以将List<String>传递给类型List的参数,但是不能将它传给类型List<Object>的参数。
无限制的通配符类型
有了泛型之后呢会有一种比较安全的替代方法,称作无限制的通配符类型(Unbounded wildcard type)。
如果要使用泛型,但不确定或者不关心实际的类型参数,就可以使用一个问号替代。例如,泛型Set<E> 的无限制通配符类型为 Set<?>(读作“某个类型的集合”)。这是最普通的参数化Set集合,可以持有任何集合
无限制通配符类型Set<?> 和原生态类型Set的区别
这个问号真正起到作用了吗?这个是当然起到作用的,因为通配符类型时安全的,原生态类型不安全。由于可以将任何元素放进原生态类型的集合中,因此很容易破坏改集合的类型约束条件;
总之,使用原生态类型会在运行时导致异常,因此不要再新代码中使用。但就有人问既然这么不推荐使用,为什么还要存在原生态类型呢?原生态类型只是为了与引入泛型之前的遗留代码进行兼容和互换而提供的。让我们做个快速的回顾:Set<Object> 是个参数化类型,所以可以包含任何对象类型的一个集合;Set<?> 则是一个通配符类型,表示只能包含某种位置对象类型的一个集合;Set则是原生态类型,它脱离了泛型系统。前两个是安全的,最后一种不安全。