接上篇:https://developer.aliyun.com/article/1228289?groupCode=java
三、 泛型对象赋值
Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,即把数据类型做为一个参数使用。
1. 问题现象
在做用户数据分页查询时,因为笔误编写了如下代码:
1) PageDataVO.java
2) UserDAO.java
3) UserService.java
以上代码没有任何编译问题,但是却把UserDO中一些涉密字段返回给前端。细心的读者可能已经发现了,在UserService类的queryUser方法的语句“return new PageDataVO(totalCount,dataList);”中,我们把List对象dataList赋值给了PageDataVO的List字段dataList。
问题是:为什么开发工具不报编译错误啦?
2. 问题分析
由于历史原因,参数化类型和原始类型需要兼容。我们以ArrayList举例子,来看看如何兼容的。
以前的写法:
现在的写法:
考虑到与以前的代码兼容,各种对象引用之间传值,必然会出现以下的情况:
所以,Java编译器对以上两种类型进行了兼容,不会出现编译错误,但会出现编译告警。但是,我的开发工具在编译时真没出现过告警。
再来分析我们遇到的问题,实际上同时命中了两种情况:
• 把List对象赋值给List,命中了第一种情况;
• 把PageDataVO对象赋值给PageDataVO,命中了第二种情况。
最终的效果就是:我们神奇地把List对象赋值给了List。
问题的根源就是:我们在初始化PageDataVO对象时,没有要求强制进行类型检查。
3. 避坑方法
1) 在初始化泛型对象时,推荐使用diamond语法
在《阿里巴巴Java开发手册》中,有这么一条推荐规则:
【推荐】集合泛型定义时,在JDK7及以上,使用diamond语法或全省略。
说明:
菱形泛型,即 diamond,直接使用<>来指代前边已经指定的类型。
正例:
其实,初始化泛型对象时,全省略是不推荐的。这样会避免类型检查,从而造成上面的问题。
在初始化泛型对象时,推荐使用diamond语法,代码如下:
现在,在Eclipse的问题窗口中,我们会看到这样的错误:
于是,我们就知道忘记把List对象转化为List对象了。
接下篇:https://developer.aliyun.com/article/1228287?spm=a2c6h.13148508.setting.22.7be64f0ebemzoR