什么是JAVA泛型的原生类型(raw type),为什么不建议使用?

什么是JAVA泛型的原生类型(raw type),为什么不建议使用?

在我们写代码的时候,如果无意间写出下面的代码:

List names = new ArrayList();
...

在编译时,javac会提示:Raw use of parameterized class 'List',那么,什么是raw type呢?

raw type的历史渊源

在很久很久以前,java还没有泛型,如果要声明一个名称的列表,可能代码是这样的

// name is string
List names = new ArrayList();

使用这个列表时,需要这样使用:

names.add("张三");
...
for (int i = 0; i < names.size(); i++) {
    String name = (String)names.get(i);
    ...
}

可以看到,每次取列表的值时,都需要进行一次强制类型转换,非常繁琐;而且在使用时还要时刻注意列表里面存储的类型,使用起来很不方便。更严重的是,列表里面的内容只能人工确保类型一致,很可能出现问题,比如下面这样:

// 加了一个int进去!
names.add(1);

在使用时,代码还是(String)names.get(i);,那么会在运行时得到一个类型转换错误,导致线上BUG。

泛型横空出世

为了解决上面的问题,java在1.5后增加了泛型,上面的代码就可以改写成这样的:

List<String> names = new ArrayList<>();
names.add("xxx");
for (int i = 0; i < names.size(); i++) {
    String name = names.get(i);
    ...
}

在编写代码的时候,声明自己存储的是字符串类型,编译器就可以自动完成强制类型转换,不必再手动转换了。而且,当我们尝试将一个其他类型的值放到列表中时,编译器会直接报错,如下所示:

names.add(1);
// 'add(java.lang.String)' in 'java.util.List' cannot be applied to '(int)'

编译器会帮助我们做类型检查,防止错误类型进入。

什么是raw type,为什么不建议使用

现在可以回答什么是raw type了。raw type就是定义了泛型的类中,不带任何实际类型参数的那种类型。比如List<E>的类型参数是E,那么不带类型参数的List就是原生类型了。
由此可见,原生类型是一个历史遗留的问题,他的存在是为了兼容没有泛型时的老代码。
使用泛型,可以获得安全性(类型检查)和描述性(类型参数)的优势,而使用原生类型则已经没有任何优势。

List<Object>List<?>与原生类型的区别

实践中,我们也会遇到List<Object>List<?>这两种看起来和原生类型很像的,特别是List<?>,那么,他们和原生类型有什么区别呢?

List<Object>与原生类型

List<Object>是一个参数化的List,他的类型参数为Object,相当于明确告知编译器这个列表可以持有任意类型的对象,使用这个仍然是类型安全的,和其他的类型参数相比,没有明显区别。
但是,如果我们有一个List<String>,想把它赋值给List<Object>,是不合法的,因为他俩不是同一类型。将List<Object>声明为List<? extends Object>,才可以。如下所示:

List<String> names = new ArrayList<>();

List<Object> objects;
// 非法:Incompatible types
// objects = names;

List<? extends Object> objectExtends;
// 合法
objectExtends = names;

List<?>与原生类型

List<?>中的?是通配符,通配符可以被? extends或者? super来限制,如果没有添加任何限制,则是无限制的通配符,说明这个参数可以是任意集合。使用List<?>是类型安全的,因为它不可以将除了null以外的任何值放到集合中(原生类型List则可以将任何值放到集合中,导致类型不安全。)

使用raw type的例外场景

除非迫不得已,不要使用原生类型。下面的情形就是迫不得已的时候,必须要使用原生态类型了。
在获取带泛型的类的class对象时,必须使用原生类型。就是写成List.class是合法的,而List<String>.class就是非法的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值