当前位置: 首页 / 技术分享 / 正文
集合泛型不匹配导致的ClassCastException异常解决过程

2023-01-06

泛型 类型   

  一. 代码重现

  前几天有个学生小K编写集合代码时,运行的结果中却出现了一个自己没见过的异常,他不知道怎么解决,于是就跑来找辉哥帮忙。下面就是小K的代码,大家可以来看看,如下所示:

图片 1

  上述代码,一旦运行就会出现下图中的异常现象。说实话,对辉哥来说,只要一遇到bug,真是瞬间感觉连吃大盘鸡都不香了,必须立马盘它才行。

图片 2

  上图中,我们看到了一个叫做ClassCastException类型转换的异常!为什么会出现这个bug呢?其实如果我们仔细检查一下代码,就会发现原来是集合中的值写错了!我们声明的集合泛型是Double类型的,结果添加数据元素的时候,给集合添加了一个整型的元素,这样就造成了上述异常。而且根据错误信息的提示,异常出现在代码的第40行位置,现在我们知道了异常的原因和位置,接下来解决就容易了。

  二. bug分析

  其实上述代码中之所以会出现问题,是因为集合对泛型的严格要求所导致的。一开始小K觉着int类型可以直接转换为double类型,所以就往集合中添加了整型数据。但实际上Java中的集合泛型,要求的必须是包装类,我们的代码中就是Interger和Double,所以是无法将基本类型直接转为包装类型的。但小K却不明白,为什么基本类型与包装类型两者的类型不一致,但在往集合中添加数据时却可以添加进去呢?为了给小K讲明白这个问题,辉哥就通过javap命令带小K查看了反编译后的List类型,我们来看看泛型的底层究竟是个什么情况,如下图所示:

图片 3

  通过反编译可以看出,集合在底层编译时,其实所谓的泛型都被擦除了。也就是说,当我们在使用泛型时,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象。所以List和List在运行时事实上是相同的类型。而这其中原始类型的集合是特别容易出问题的,因为原始类型会跳过泛型检查且很不安全,List、List 和 List 等存在着巨大的差异,泛型在使用中很容易造成类型擦除。那么到底什么是泛型擦除?我们继续往下看。

  三. 泛型的擦除

  我们知道,Java泛型这个特性并不是一开始就有的,而是从JDK 1.5才开始加入的。因此Sun公司为了兼容之前的旧版本,Java对泛型的实现采取了“伪泛型”的策略,也就是说Java在语法上支持泛型,但在编译阶段会进行所谓的“类型擦除”(Type Erasure),将所有的泛型表示(尖括号中的内容)都替换为具体的类型(其对应的原生态类型),就像完全没有泛型一样。

  并且泛型在擦除的时候,还会根据泛型的具体类型来进行。

  四. 泛型相关知识回顾

  泛型其实就是引用类型的占位符,主要用于避免引用类型的相互转换,替换之前使用的Object类型,去除不同类型之间的强转。

  1. 泛型的应用

  泛型主要可以用在 泛型类、泛型接口、泛型方法 上,也就是说,泛型可以在类、接口、方法上使用。

  2. 泛型通配符

  在泛型中,有几个常用的通配符,我们需要掌握。

  ?:表示右边的泛型可以是任意类型,还可以指定一个泛型的上限和下限。

  泛型上限:

  - 语法格式: 类型名称 对象名称

  - 语法意义: 只能接收该类型及其子类

  泛型下限:

  - 语法格式: 类型名称 对象名称

  - 语法意义: 只能接收该类型及其父类型

  具体用法,如下图所示:

图片 4

  现在你知道为什么会出现上述异常了吗?对泛型的理解是否有进一步加深了呢?如果还有不明白的地方,可以给客服留言,客服会及时给你回复的。

分享: 更多

上一篇:YARN的Job提交流程

下一篇:校园疫情信息化系统

好程序员公众号

  • · 剖析行业发展趋势
  • · 汇聚企业项目源码

好程序员开班动态

More+
  • HTML5大前端 <高端班>

    开班时间:2021-04-12(深圳)

    开班盛况

    开班时间:2021-05-17(北京)

    开班盛况
  • 大数据+人工智能 <高端班>

    开班时间:2021-03-22(杭州)

    开班盛况

    开班时间:2021-04-26(北京)

    开班盛况
  • JavaEE分布式开发 <高端班>

    开班时间:2021-05-10(北京)

    开班盛况

    开班时间:2021-02-22(北京)

    开班盛况
  • Python人工智能+数据分析 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2020-09-21(上海)

    开班盛况
  • 云计算开发 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2019-07-22(北京)

    开班盛况
在线咨询
试听
入学教程
立即报名

Copyright 2011-2023 北京千锋互联科技有限公司 .All Right 京ICP备12003911号-5 京公网安备 11010802035720号