问题发生
- 项目工具及框架: mybatis-plus,springboot,jackson做json序列化处理器。
- 业务需求:搞了一个字段,字段类型是json。字段在java对应中对应的属性是一个枚举类型的List.
- 展现情况:利用mybatis-plus,存入时很正常的存入了枚举name组成的数组。查看的时候出现了问题,取出对象时是正常的。而当我访问那个枚举数组时,只要一访问这其中的元素,就出现了报错。
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Enum
问题定位
当时第一反应肯定是自己代码写的有问题,因为单个枚举类是可以直接转换的,存取都没有问题。确认了一下,没有问题。
然后也排除了jackson,mybatis-plus的问题,因为存入是正常的,而且报错的异常似乎来自于jdk。
最后通过断点和vm那些命令的方式,发现在访问这个元素前,我看不到这个数组下面的元素类型居然是string。。
确定问题–Java类型擦除
由于java的泛型是伪泛型,因为Java在编译期间,所有的泛型相关信息都会被“擦掉“,字节码中不包含任何类型信息,简单来说在编译器层次实现泛型时,生成的字节码是不包含泛型中的类型信息的。
举个例子,比如List和HashMap这样的容器,如论List还是List 在编译过程中,都会变成List,JVM对泛型是看不到的(C++没有这个坑),在对访问这些元素的时候,有时候就会出现问题。因为访问元素时会更具类型走强转,比如说Object i ,会用(Integer)i,如果是基本类型的包装类确实可以直接强转,而使用枚举类,强转就会报上面的错。
解决问题
目前用的一种比较粗暴的方法。声明一个类继承ArrayList,声明构造方法,使用这个类去定义属性即可。
应该还有从枚举本身出发的方法