EffectiveJava(23)为什么不能在新生代码中使用原生态类型

泛型类和泛型接口
声明一个或者多个类型参数的类或者接口.
为什么不要在新代码中使用原生态类型
原生态类型,即泛型不带参数的类型 如List的list,list就是其原生态类型
1.使用原生态类型,插入数据时,IDE会绕过编译,从将错误升级成运行时错误.而此时如果你写的代码已经离原生态类型很远,那么错误将很难调试.
如:

private final Collection stamps = ...;
        stamps.add(new Coin(...));
我们知道尝试取出这个类型时才会显示错误
    for(Iterator i = stamps.iterator();it.hasNext();){
            //这里将会抛出一个类型转换异常(ClassCastException)
            Stamp s = (Stamp)i.next();
        }
使用泛型
    private final Collection<Stamp> stamps = ...;
        stamps.add(new Coin(...));
此时当stamps集合中添加非stamp元素时,编译器会直接报错,显示类型错误(error type)

2.从集合中删除元素时不再需要进行手工转换.编译器会为我们插入隐式的转换并确保他们不会失败.(使用泛型)
如:
        for(Stamp s:stamps){
            //Do something
        }
    //传统循环
    for(Iterator<Stamp> i = stamps.iterator();i.hasNext()){
        Stamp s = i.next();
        //Do Something
    }

移植兼容性:代码必须合法,才能将参数化的实例传递给那些被设计城市用普通类型的方法,反之亦然.

List 和 List<Object>
    List将会失去安全性
    public static void main(String[] args){
        List<String> strings = new ArrayList<String>();
        unsafeAdd(strings,new Integer(42));
        String s = string.get(0);
    }
    private static void unsafeAdd(List list,Object o){
        list.add(o);
    }
它可以被编译,但是会因为使用原生态类型收到一条警告.如果换成
    private static void unsafeAdd(List<Object> list,Object o){
        list.add(o);
    }
将无法通过编译

3.即使你不确定或不在乎集合元素类型,也要使用无限制的通配符类型来充当泛型的参数类型

    static int numElementsInCommon(Set s1,Set s2){
        int result = 0;
        for(Object o1:s1){
            if(s2.contains(01))
                result++;
        }
        return result;
    }
    ----->>>>
    static int numElementsInCommon(Set<?> s1,Set<?> s2){
你可以将任何元素插入到原生态类型中,但你不能把除了null以外的任何元素放入set<?>中,否则将会报错

那我们在何时可以使用原生态类型呢?如果不能被使用,那java为什么不移除它?
确实有两种特殊情况使用原生态类型的例子
a.在类文字中必须使用原生态类型.规范不允许使用参数化类型.
如:List

        if(o instanceof Set){
            //受检转换
            Set<?> m = (Set<?>)o;
        }

总结:使用原生态类型会在运行时导致异常,因此不要在新代码中使用.原生态类型只是为了引入泛型之前遗留代码进行兼容和互用而提供的.
Set 是个参数化类型,表示可以包含任何对象类型的一个集合 safe
Set

原文地址:https://www.cnblogs.com/qwop/p/6637286.html