a63181182
a63181182
2015-02-12 04:18
采纳率: 100%
浏览 2.1k
已采纳

JAVA中使用泛型擦除的问题

import java.util.ArrayList;

public class Fanxing {

 public static void main(String[] args) throws Exception{  
     ArrayList<Integer> arrayList3=new ArrayList<Integer>();
     arrayList3.add(1);//这样调用add方法只能存储整形,因为泛型类型的实例为Integer
     arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, "asd");
     for (int i=0;i<arrayList3.size();i++) {
        System.out.println(arrayList3.get(i));
     }


     ArrayList<String> arrayList2=new ArrayList<String>();
     arrayList2.add("asd");//这样调用add方法只能
        存储整形,因为泛型类型的实例为Integer
     arrayList2.getClass().getMethod("add", Object.class).invoke(arrayList2, 1);
     for (int i=0;i<arrayList2.size();i++) {
        System.out.println(arrayList2.get(i));
    }
 }  

}
输出结果为:
1
asd
asd
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at Fanxing.main(Fanxing.java:19)

请问这是什么问题?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

5条回答 默认 最新

  • lycccxzt
    lycccxzt 2015-02-12 07:27
    已采纳
       我运行了下, 找到原因了, 原因是System.out.println() 造成的。
       这个方法可传的参数为基础类型和Object对象,还提供了一个String对象的方法参数。
       第一个例子中List是Integer泛型,System.out.println() 是没有提供对应的方法参数, 所以会调用Object参数的方法,Integer转Object是没问题的,所以通过了。
       第二个例子中List是String泛型,System.out.println() 提供了String参数的就去,所以用的是以String为参数的方法,但是list中的第2个值你用了反射传的是个数值,这里会做个强转,从Integer转成String,所以出错。
    
    点赞 评论
  • yj83855039
    小鸭无罪 2015-02-12 06:32

    object包括基础类型,所以第一个打印没问题,Interger不是基础类型,所以第二个不行

    点赞 评论
  • lonelybishuilanting
    Flying_L 2015-02-12 07:25

    泛型仅仅是用于定义一个不确定内容对象类型的类,但是在实例化之后,泛型中的T一定已经确定了。arrayList3已经确定了这个list中只能存放integer对象了。所以你后面的调用肯定会出错。

    点赞 评论
  • lycccxzt
    lycccxzt 2015-02-12 07:34

    ArrayList arrayList3=new ArrayList();
    arrayList3.add(1);//这样调用add方法只能存储整形,因为泛型类型的实例为Integer
    arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, "asd");
    for (int i=0;i<arrayList3.size();i++) {
    System.out.println(arrayList3.get(i));
    }

        ArrayList<String> arrayList2=new ArrayList<String>();
        arrayList2.add("23");
        arrayList2.getClass().getMethod("add", Object.class).invoke(arrayList2, 1);
        for (int i=0;i<arrayList2.size();i++) {
            String s = ((Object)arrayList2.get(i)).toString();
            System.out.println(s);
       }
    
    点赞 评论
  • lonelybishuilanting
    Flying_L 2015-02-12 07:49

    Java的泛型是伪泛型。为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉。正确理解泛型概念的首要前提是理解类型擦出(type erasure)。
    Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。
    如在代码中定义的List和List等类型,在编译后都会变成List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。类型擦除也是Java的泛型实现方法与C++模版机制实现方式之间的重要区别。

    点赞 评论

相关推荐