关于java利用反射调用泛型类型的问题

和泥小工 2012-12-02 06:23:49
今天在看张孝祥老师讲的一个泛型的知识点时,碰到了一个问题,张老师说泛型只是给编译器看的,以张老师举的例子说明:
都是ArrayList类型的对象,一个是String型(ArrayList<String>)arr1,另一个是Integer型(ArrayList<Integer>)arr2,这两个对象在编译完成后生成的字节码是相同的,利用反射调用add方法时应该可以把泛型屏蔽的,但是我碰到了下面的问题,代码如下:

ArrayList<Integer> arr1 = new ArrayList<Integer>();
arr1.getClass().getMethod("add", Object.class).invoke(arr1, "abc");
System.out.println(arr1.get(0));

上面这个没有问题,可以把泛型屏蔽掉,但是下面的却不行:

ArrayList<String> arr2 = new ArrayList<String>();
arr2.getClass().getMethod("add", Object.class).invoke(arr2, 2);
System.out.println(arr2.get(0));

运行报了异常:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at day1.GenericTest.main(GenericTest.java:30)


不知道为什么,String型的可以屏蔽,Integer的却不行,有哪位高手能指点一下。
...全文
508 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
keep thinking 2021-08-01
  • 打赏
  • 举报
回复

测试案例:有兴趣的可以看看
package com.atguigu.反射;

import org.junit.Test;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class 带泛型的反射 {

//还得用反射取出来才可以骗过编译器
@Test
public  void test1()throws Exception {
    ArrayList<String> arr2 = new ArrayList<String>();
    arr2.getClass().getMethod("add", Object.class)
            .invoke(arr2, 2);
    System.out.println(arr2.getClass().getMethod("get",int.class)
            .invoke(arr2, 0));
    //System.out.println(arr2.get(0));//这里编译器认为取出来的是String
}
/*
今天在看张孝祥老师讲的一个泛型的知识点时,碰到了一个问题,张老师说泛型只是给编译器看的,以张老师举的例子说明:

都是ArrayList类型的对象,一个是String型(ArrayList)arr1,另一个是Integer型(ArrayList)arr2,
这两个对象在编译完成后生成的字节码是相同的,
利用反射调用add方法时应该可以把泛型屏蔽的,但是我碰到了下面的问题,代码如下:
*/
@Test
public void test2()throws Exception {
ArrayList arr1 = new ArrayList();
Method method = arr1.getClass().getMethod("add", Object.class);
//这里操作泛型,表面集合arr1中存储的都是Integer型,经过反射一顿操作后里面存储了一些其它类型
//的数据了,此时的ArrayList集合相当于从ArrayList转变到ArrayList
//此时在进行循环遍历时就不能使用Java8的forEach循环遍历了。
/*此时应该使用进行遍历
* for(Object o:arr1){
System.out.println(o);
}
*/
method.invoke(arr1,'A');
method.invoke(arr1, 2);
method.invoke(arr1,true);
method.invoke(arr1,3.14);
method.invoke(arr1,6.18f);
method.invoke(arr1,"tom");

    System.out.println(arr1.get(0));
    System.out.println(arr1.get(1));
    System.out.println(arr1.get(2));
    System.out.println(arr1.get(3));
    System.out.println(arr1.get(4));
    System.out.println(arr1.get(5));
    System.out.println("arr1........................");
    for(Object o:arr1){
        System.out.println(o);
    }

    System.out.println("lllllllllllllllllllll");
    try {

// java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Integer
arr1.stream().forEach(System.out::println);
}catch (Exception e){
e.printStackTrace();
}
try {
// //java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
arr1.forEach(x->System.out.println(String.valueOf(x)));
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void test3()throws Exception {
ArrayList arr2 = new ArrayList();
arr2.getClass().getMethod("add", Object.class)
.invoke(arr2, 2);
System.out.println(arr2.get(0));
}
@Test
public void test4()throws Exception {
ArrayList arr2 = new ArrayList();
Method method = arr2.getClass().getMethod("add", Object.class);

    method.invoke(arr2,'A');
    method.invoke(arr2, 2);
    method.invoke(arr2,true);
    method.invoke(arr2,3.14);
    method.invoke(arr2,6.18f);
    method.invoke(arr2,"tom");

// String s = arr2.get(0).toString();
// java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.String
// System.out.println(String.valueOf(s));
// System.out.println(s);

    System.out.println(arr2);
    System.out.println("-------------------------------1");
    System.out.println(String.valueOf(arr2.get(0)));
    System.out.println(String.valueOf(arr2.get(1)));
    System.out.println(String.valueOf(arr2.get(2)));
    System.out.println(String.valueOf(arr2.get(3)));
    System.out.println(String.valueOf(arr2.get(4)));
    System.out.println(String.valueOf(arr2.get(5)));
    System.out.println("-------------------------------2");

// System.out.println(arr2.get(0)+"");
for(Object o:arr2){
System.out.println(o);
}

    try {
        arr2.stream().forEach(System.out::println);
    }catch (Exception e){
        e.printStackTrace();
    }

    try {

// //java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
arr2.forEach(x->System.out.println(String.valueOf(x)));
}catch (Exception e){
e.printStackTrace();
}

    System.out.println("************************************");
    List<? extends Serializable> a = Arrays.asList(11, "aa", true, 33.14, 66.18f);
    a.forEach(System.out::println);
    List<Object> b=new ArrayList<>();
    b.add("zs");
    b.add(33);
    b.add(true);
    b.add(10.14);
    b.forEach(System.out::println);
    System.out.println("hahahhaha");
    b.forEach(x->System.out.println(String.valueOf(x)));
}


public static void main(String args[]) throws Exception {
    ArrayList<Integer> arr1 = new ArrayList<Integer>();
    arr1.add(1);
    System.out.println(arr1.get(0));

    ArrayList<Object> arr3 = new ArrayList<Object>();
    arr3.add("abc");
    System.out.println(arr3.get(0));

    ArrayList<Te> arr4 = new ArrayList<Te>();
    arr4.add(new Te());
    System.out.println(arr4.get(0));

    ArrayList arr5 = new ArrayList();
    arr5.add("abc");
    System.out.println(arr5.get(0));

    ArrayList<String> arr2 = new ArrayList<String>();
    arr2.add("abc");
    System.out.println(arr2.get(0));
}

}
class Te{

}

keep thinking 2021-08-01
  • 打赏
  • 举报
回复

这里操作泛型,表面集合arr1中存储的都是Integer型,经过反射一顿操作后里面存储了一些其它类型
的数据了,此时的ArrayList集合相当于从ArrayList转变到ArrayList
此时在进行循环遍历时就不能使用Java8的forEach循环遍历了

faping_cao 2012-12-03
  • 打赏
  • 举报
回复 1

public static void main(String args[]) throws Exception {
		ArrayList<Integer> arr1 = new ArrayList<Integer>();
		arr1.add(1);
		System.out.println(arr1.get(0));

		ArrayList<Object> arr3 = new ArrayList<Object>();
		arr3.add("abc");
		System.out.println(arr3.get(0));

		ArrayList<Test3> arr4 = new ArrayList<Test3>();
		arr4.add(new Test3());
		System.out.println(arr4.get(0));

		ArrayList arr5 = new ArrayList();
		arr5.add("abc");
		System.out.println(arr5.get(0));

		ArrayList<String> arr2 = new ArrayList<String>();
		arr2.add("abc");
		System.out.println(arr2.get(0));
	}

public static void main(java.lang.String[])   throws java.lang.Exception;
  Code:
   0:   new     #2; //class java/util/ArrayList
   3:   dup
   4:   invokespecial   #3; //Method java/util/ArrayList."<init>":()V
   7:   astore_1
   8:   aload_1
   9:   iconst_1
   10:  invokestatic    #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
   13:  invokevirtual   #5; //Method java/util/ArrayList.add:(Ljava/lang/Object;
)Z
   16:  pop
   17:  getstatic       #6; //Field java/lang/System.out:Ljava/io/PrintStream;
   20:  aload_1
   21:  iconst_0
   22:  invokevirtual   #7; //Method java/util/ArrayList.get:(I)Ljava/lang/Objec
t;
   25:  invokevirtual   #8; //Method java/io/PrintStream.println:(Ljava/lang/Obj
ect;)V
   28:  new     #2; //class java/util/ArrayList
   31:  dup
   32:  invokespecial   #3; //Method java/util/ArrayList."<init>":()V
   35:  astore_2
   36:  aload_2
   37:  ldc     #9; //String abc
   39:  invokevirtual   #5; //Method java/util/ArrayList.add:(Ljava/lang/Object;
)Z
   42:  pop
   43:  getstatic       #6; //Field java/lang/System.out:Ljava/io/PrintStream;
   46:  aload_2
   47:  iconst_0
   48:  invokevirtual   #7; //Method java/util/ArrayList.get:(I)Ljava/lang/Objec
t;
   51:  invokevirtual   #8; //Method java/io/PrintStream.println:(Ljava/lang/Obj
ect;)V
   54:  new     #2; //class java/util/ArrayList
   57:  dup
   58:  invokespecial   #3; //Method java/util/ArrayList."<init>":()V
   61:  astore_3
   62:  aload_3
   63:  new     #10; //class Test3
   66:  dup
   67:  invokespecial   #11; //Method Test3."<init>":()V
   70:  invokevirtual   #5; //Method java/util/ArrayList.add:(Ljava/lang/Object;
)Z
   73:  pop
   74:  getstatic       #6; //Field java/lang/System.out:Ljava/io/PrintStream;
   77:  aload_3
   78:  iconst_0
   79:  invokevirtual   #7; //Method java/util/ArrayList.get:(I)Ljava/lang/Objec
t;
   82:  invokevirtual   #8; //Method java/io/PrintStream.println:(Ljava/lang/Obj
ect;)V
   85:  new     #2; //class java/util/ArrayList
   88:  dup
   89:  invokespecial   #3; //Method java/util/ArrayList."<init>":()V
   92:  astore  4
   94:  aload   4
   96:  ldc     #9; //String abc
   98:  invokevirtual   #5; //Method java/util/ArrayList.add:(Ljava/lang/Object;
)Z
   101: pop
   102: getstatic       #6; //Field java/lang/System.out:Ljava/io/PrintStream;
   105: aload   4
   107: iconst_0
   108: invokevirtual   #7; //Method java/util/ArrayList.get:(I)Ljava/lang/Objec
t;
   111: invokevirtual   #8; //Method java/io/PrintStream.println:(Ljava/lang/Obj
ect;)V
   114: new     #2; //class java/util/ArrayList
   117: dup
   118: invokespecial   #3; //Method java/util/ArrayList."<init>":()V
   121: astore  5
   123: aload   5
   125: ldc     #9; //String abc
   127: invokevirtual   #5; //Method java/util/ArrayList.add:(Ljava/lang/Object;
)Z
   130: pop
   131: getstatic       #6; //Field java/lang/System.out:Ljava/io/PrintStream;
   134: aload   5
   136: iconst_0
   137: invokevirtual   #7; //Method java/util/ArrayList.get:(I)Ljava/lang/Objec
t;
   140: checkcast       #12; //class java/lang/String  
   143: invokevirtual   #13; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   146: return

}
字节码不一样。 当ArrayList<String>的时候,字节码多了checkcast #12; //class java/lang/String
xingfuzhuzi1314 2012-12-03
  • 打赏
  • 举报
回复
和泥小工 2012-12-03
  • 打赏
  • 举报
回复
谢谢各位,明白了
suciver 2012-12-03
  • 打赏
  • 举报
回复
引用 6 楼 goldenfish1919 的回复:
Java code?? 12345678 //还得用反射取出来才可以骗过编译器 public static void main(String[] args)throws Exception { ArrayList<String> arr2 = new ArrayList<String>(); arr2.getClass().getMethod("……
正解
若鱼1919 2012-12-03
  • 打赏
  • 举报
回复

//还得用反射取出来才可以骗过编译器
public static void main(String[] args)throws Exception {
        ArrayList<String> arr2 = new ArrayList<String>();
        arr2.getClass().getMethod("add", Object.class).invoke(arr2, 2);
        System.out.println(arr2.getClass().getMethod("get",int.class).invoke(arr2, 0));
        //System.out.println(arr2.get(0));//这里编译器认为取出来的是String
	}
snow-is-my-Love 2012-12-03
  • 打赏
  • 举报
回复
引用 2 楼 xodbc 的回复:
如果是第二个,我猜是调用了System.out.println(String str)这个方法,而你传入的是Integer,你可以试试: System.out.println(arr2.get(0)+"");
错误行 一定是 System.out.println(arr2.get(0)); System.out.println(arr2.get(0)+""); 这样 也是不行的 可以直接 System.out.println(arr2),其实 你已经绕开了,已经添加进去了
xingfuzhuzi1314 2012-12-03
  • 打赏
  • 举报
回复
LZ, 这个也是可以屏蔽的,错误原因是由于你的System.out.println(arr2.get(0));

ArrayList<String> arr2 = new ArrayList<String>();
	      arr2.getClass().getMethod("add", Object.class).invoke(arr2, 2);
	      System.out.println(String.valueOf(arr2.get(0)));
这样程序就正常OK,输出为2!
huifeng773950918 2012-12-03
  • 打赏
  • 举报
回复
不是不行,你new出来的集合放的是String类型的数据,你传进去的是Integer(int)类型的数据,当然报类型转换错误了。
为啥呢 2012-12-03
  • 打赏
  • 举报
回复
错误行数是这行: arr2.getClass().getMethod("add", Object.class).invoke(arr2, 2); 还是这行? System.out.println(arr2.get(0)); 如果是第二个,我猜是调用了System.out.println(String str)这个方法,而你传入的是Integer,你可以试试: System.out.println(arr2.get(0)+"");
和泥小工 2012-12-03
  • 打赏
  • 举报
回复
怎么没人告诉我呢

62,633

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧