关于JAVA泛型数组类型擦除引发的问题及解决方案(java arraylist 泛型)

  本篇文章为你整理了关于JAVA泛型数组类型擦除引发的问题及解决方案(java arraylist 泛型)的详细内容,包含有java 泛型擦除 java arraylist 泛型 jvm泛型擦除 java泛型基本数据类型 关于JAVA泛型数组类型擦除引发的问题及解决方案,希望能帮助你了解 关于JAVA泛型数组类型擦除引发的问题及解决方案。

  先看如下一个DEMO示例代码:(其中doBatchGet被子类重写了1次)

  

public abstract class BaseDemoService T {

 

   public String batchGet(T... ints) {

   T one=ints[0];

   System.out.println("one class:" + one.getClass().getCanonicalName());

   return doBatchGet(one);

   public String doBatchGet(T... ints){

   System.out.println("com.example.springwebapp.service.Demo1Service.doBatchGet");

   return String.join(",", Arrays.toString(ints));

   public String doGet(T one){

   return one.toString();

  @Service

  public class Demo1Service extends BaseDemoService Integer {

   @Override

   public String doBatchGet(Integer... ints) {

   System.out.println("com.example.springwebapp.service.Demo1Service.doBatchGet");

   return super.doBatchGet(ints);

  
Integer[] ints={1,2,3,4,5,6};

   System.out.println("batchGet result:" + baseDemoService.batchGet(ints));

  

 

  大家认为最后batchGet result输出的结果如何?有人可能会认为这太简单了,就是1,但实际上的结果可能会让你打脸,居然直接报错,如下所示:

  

one class:java.lang.Integer

 

  java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;

   at com.example.springwebapp.service.Demo1Service.doBatchGet(Demo1Service.java:5)

   at com.example.springwebapp.service.BaseDemoService.batchGet(BaseDemoService.java:11)

   at com.example.springwebapp.Springwebapp1ApplicationTests.testOverride(Springwebapp1ApplicationTests.java:38)

  ... ...

  

 

  报错的意思是类型转换错误,object数组类型不能转换为integer数组类型,但我上面一行明明输出的结果就是one class:java.lang.Integer,为何传给doBatchGet就变成了object类型呢?是不是有点看不懂了,编译也是正常的,但运行就是报错,如果把入参的ints直接传到doBatchGet方法入参中也是OK的,或者内部将doBatchGet改为doGet,即使子类重写doGet一样可以正确获取结果 又或者doBatchGet没有被子类重写也可以正确获得结果,但如果单独从ints中取一个成员然后再调doBatchGet方法就会报错,大家知道为啥吗?

  我这里就不卖关子了,其实就是泛型参数类型擦除“惹的祸”,因为别看我们是BaseDemoService,其实这个T在编译后就是一个Object,在从ints取出一个成员值one后,虽然指明是T,但实际就是Object,最后在调doBatchGet的时候,JVM会将one这个变量隐式转换为one的Object数组,然后调doBatchGet,由于doBatchGet方法被子类重写,而重写后入参是具体的类型(Integer数组),这样就导致了上面的object数组类型不能转换为integer数组类型的错误。

  当我们知道了问题原因后,那么就可以对症下药了.

  解法一(关键点:通过反射创建一个入参真实类型的数组,这个数组与doBatchGet入参类型一致):

  

 public String batchGet(T... ints) {

 

   T[] arr = (T[]) Array.newInstance(ints[0].getClass(), 1);

   arr[0]=ints[0];

   System.out.println("arr class:" + arr.getClass().getCanonicalName());

   return doBatchGet(arr);

  

 

  解法二(关键点:将doBatchGet由原来的可变参数直接改为List,这样即使子类重写,因为List本身就是泛型,所以擦除了就都是一样的):

  

 public String batchGet(T... ints) {

 

   return doBatchGet(Arrays.asList(ints));

  public String doBatchGet(List T ints){

   System.out.println("com.example.springwebapp.service.Demo1Service.doBatchGet");

   return ints.toString();

  

 

  以上就是实际项目中碰到的问题及解法,希望对大家也有帮助。

  以上就是关于JAVA泛型数组类型擦除引发的问题及解决方案(java arraylist 泛型)的详细内容,想要了解更多 关于JAVA泛型数组类型擦除引发的问题及解决方案的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: