62,633
社区成员
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));
测试案例:有兴趣的可以看看
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{
}
这里操作泛型,表面集合arr1中存储的都是Integer型,经过反射一顿操作后里面存储了一些其它类型
的数据了,此时的ArrayList集合相当于从ArrayList转变到ArrayList
此时在进行循环遍历时就不能使用Java8的forEach循环遍历了
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
//还得用反射取出来才可以骗过编译器
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
}
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!