博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
记一次由于Java泛型类型擦除而导致的问题,及解决办法
阅读量:5026 次
发布时间:2019-06-12

本文共 2420 字,大约阅读时间需要 8 分钟。

中所周知,Java中的泛型并不像C++、C#一样是真正的泛型,其泛型是通过类型擦除来实现的。具体什么是类型擦除,可以参看这篇博文:。今天要记录的是在实际开发中遇到的一个,由于Java这种泛型的实现方式而导致的问题,及解决办法。

 

一下代码是模拟真实开发环境下的实现:

1   @Test 2   public void test(){ 3     // 构建searchMap,模拟前端传来的查询参数 4     Map
searchMap = new HashMap
(); 5 List
goodsIds1 = new ArrayList
(); 6 goodsIds1.add(1); 7 goodsIds1.add(2); 8 goodsIds1.add(3); 9 searchMap.put("goodsIds", goodsIds1);10 searchMap.put("goodsType", 1); 11 12 // 利用searchMap进行查询,模拟后端的逻辑13 List
goodsIds2 = (List
)searchMap.get("goodsIds");14 for(Long goodsId : goodsIds2){15 System.out.println(goodsId);16 }17 }

这里的searchMap用来接收前端传来的查询商品信息的参数,假设要查询商品id分别为1、2、3,同时商品类型为1的商品。后端逻辑会从searchMap中获取goodsIds的list,然后循环查询每一个商品的信息。以上代码在eclipse中不会提示任何错误,但其实在运行的时候会抛出  java.lang.ClassCastException 异常。

 

问题就在于第9行

searchMap.put("goodsIds", goodsIds1);

中goodsIds1是List<Integer> 类型的,而第13行

List
goodsIds2 = (List
)searchMap.get("goodsIds");

在取出goodsIds的时候,虽然强制转换为List<Long>型,但实质上,goodsIds2中的值为Integer型,如下图:

所以在第14行遍历goodsIds2的时候

for(Long goodsId : goodsIds2){    System.out.println(goodsId);}

就会抛出 java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long 异常。这里本质就是由于List<Integer>和List<Long>,在编译之后,其泛型信息都被擦除,都被视为List,所以取出时能够转换成功。

 

其实在第13行,IDE会给出警告:Type safety: Unchecked cast from Object to List<Long>,虽然可以通过在方法上加注解:@SuppressWarnings("unchecked")来消除警告,但这只是起到标示作用,并不会修正错误。最简单的修复的办法就是将goodsIds2也声明为List<Integer>,然后再遍历的时候转为Long型,但是不太优雅。另外一种解决方法就是,用Java类去接收前端传来的参数,而不是用Map,但是这样的话需要增加一个POJO类。那为什么不直接将goodsIds1也声明为List<Long>型呢?像这样:

1   @Test 2   public void genericTest(){ 3     // 构建searchMap,模拟前端传来的查询参数 4     Map
searchMap = new HashMap
(); 5 List
goodsIds1 = new ArrayList
(); 6 goodsIds1.add(1L); 7 goodsIds1.add(2L); 8 goodsIds1.add(3L); 9 searchMap.put("goodsIds", goodsIds1);10 searchMap.put("goodsName", "商品1"); 11 12 // 利用searchMap进行查询,模拟后端的逻辑13 List
goodsIds2 = (List
)searchMap.get("goodsIds");14 for(Long goodsId : goodsIds2){15 System.out.println(goodsId);16 }17 }

这样做确实能够通过测试,但在实际开发中,用Map<String, Object>去接收到的参数,当数值小于Integer的最大值时,会默认将其按Integer处理。

 

转载于:https://www.cnblogs.com/HarrisonHao/p/6137573.html

你可能感兴趣的文章
CF717A Festival Organization(第一类斯特林数,斐波那契数列)
查看>>
oracle直接读写ms sqlserver数据库(二)配置透明网关
查看>>
控件发布:div2dropdownlist(div模拟dropdownlist控件)
查看>>
Oracle composite index column ordering
查看>>
大话设计模式随笔四
查看>>
关于 ORA-01439: 要更改数据类型, 则要修改的列必须为空
查看>>
Docker 生态
查看>>
Spring整合jdbc-jdbc模板api详解
查看>>
Tomcat:Can't load AMD 64-bit .dll on a IA 32 platform(问题记录)
查看>>
JAVA 集合JGL
查看>>
Python创建删除文件
查看>>
Android中创建与几种解析xml的方法
查看>>
java 网络编程(三)---TCP的基础级示例
查看>>
springboot复习小结
查看>>
C# Enum,Int,String的互相转换 枚举转换
查看>>
移动端开发兼容问题全记录
查看>>
NO.44 文字超出显示省略号后面小图标紧跟文字后面
查看>>
注册dll
查看>>
5.27 考试 + 总结
查看>>
Magento 2.2.5和2.2.6的bug 产品设置special price又删除后价格排序有误
查看>>