Effective Java之请不要在新代码中使用原生态类型(二十三)

1.泛型与原生态类型的概念

泛型就是带一个或多个类型参数E的类或者接口,而原生态类型是不带任何实际类型的泛型,例如List是原生态类型,List < String >或者List< E >是泛型。

2.泛型的作用

泛型是在jdk1.5之后添加的。

举个例子:

public class test {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Integer(2));
        String s = (String) list.get(0);
    }
}

就会在运行时抛出

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at wqeqw.test.main(test.java:10)

然而添加了泛型

public class test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList();
        list.add(new Integer(2));
        //不用显式声明类型转换
        String s = list.get(0);
    }
}

就会在编译时抛出

The method add(String) in the type ArrayList<String> is not applicable for the arguments (Integer)

而且不用显式声明类型转换。

总结:泛型的作用是将jdk1.5以前在运行期间容易发生问题的强制类型转换问题提前到编译期间检查

3.List<Object>和List的区别

先看一个例子:

public class test2 {
    public static void main(String[] args) {
        List<String>lists= new ArrayList<String>();
        test2.add(lists, 123);
        String string = lists.get(0);
    }

    public static void add(List list,Object o) {
        list.add(o);
    }
}

这里依然会发生强制转换的问题,原因是List< String >是List的子类,借此,可以通过多态这种小把戏,能让List< String >做出“出格”的行为。

而List< String >并不是List< Object >的子类,可以在编译期间就检查,防止做出小把戏。

//将List换成List<Object>
public static void add(List<Object> list,Object o) {
        list.add(o);
    }

就会在编译期间发现小把戏:

The method add(List<Object>, Object) in the type test2 is not applicable for the arguments (List<String>, int)

总结:List原生类型避免了类型检查,失去安全性,后者明确告诉编译器能够持有任何类型的对象

4.List<?>和List的区别

?是无限制通配符类型
下面来看一个例子:

public class test3 {
    public static void main(String[] args) {
        Set<String>sets1= new HashSet<String>();
        test3.add(sets1);
        test3.add2(sets1);
    }

    public static void add(Set s) {
        s.add(1);
    }
    //The method add(capture#1-of ?) in the type Set<capture#1-of ?> is not applicable for the arguments (int)
    public static void add2(Set<?> s) {
        s.add(1);
    }
}

这里在List< String >中添加Integer元素,add2方法出现编译错误。

这里实际上耍的小把戏,跟上面的例子一样,List< ? >在这里做的事情是不能将任意元素(除了null)添加到List< ? >中,这就杜绝了小把戏的出现。

但是这样的编译错误让人无法接受,无法将任意元素添加到List< ? >中,那要他有何用,于是有限制的通配符在这里就派上了用场。

总结:这里List< ? >无限制通配符的作用仅仅是防止强制类型转换问题的发生,并没有实际的作用。

5.适合原生态类型的情况

1.规范中要求:在类文字中必须用原生态类型List
比如List.class
而不能List< String >.class

2.由于泛型类型在运行时是可以擦除的,所以在xx instanceof List这样的语句中是没有问题的,变成xx instanceof List<?>反而是多余的。

总之,原生态类型只是为了与引入泛型之前的遗留代码进行兼容而提供的,除了类文字,instance两种情况,否则不要在新代码中国使用原生态类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值