开发环境JDK8:
java version "1.8.0_301"
Java(TM) SE Runtime Environment (build 1.8.0_301-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.301-b09, mixed mode)
源码如下,注意源码是可以编译通过的,你们先运行一下代码,我怕我的描述你们没看懂,[\苦笑]。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class ListReflectDemo2 {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
ArrayList<String> listStr = new ArrayList<String>();
listStr.add("只能添加String类型");
Class c2 = listStr.getClass();
Method m= c2.getMethod("add", Object.class);
m.invoke(listStr, 20);//注意listStr只能添加String类型,我们现在可以通过反射的手段绕过编译器给他加一个整形进去
System.out.println("注意整形已经添加进去了,List的元素个数为:-> " + listStr.size());
System.out.println();
Object obj = listStr;
ArrayList<Boolean> listTest = (ArrayList<Boolean>)obj;
System.out.println("看看listTest的Class类型到底是什么类型:-> " + listTest.getClass());
System.out.println("我想得到一个Boolean类型,但是得到确实String类型,这是为什么,为什么这里没报错?:-> " + listTest.get(0));
System.out.println("我想得到一个Boolean类型,但是得到确实String类型,这是为什么,为什么这里没报错?:-> " + listTest.get(1));
System.out.println("上面没报错就很奇怪,一定要搞明白");
System.out.println();
System.out.println("下面的会报错我能理解,上面的没报错我就不能理解?");
System.out.println("listStr的toString方法,注意整形也可以输出出来: " + listStr.toString());
System.out.println("看看listStr的Class类型到底是什么类型:-> " + listStr.getClass());
//Integer in = list2.get(1);编译直接就报错了
System.out.println(listStr.get(1));//这里会什么又会报错了,因为lis2认为20是String类型的,结果就报错了,java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
}
}
我的疑问如下截图:
第一个疑问:这里为什么不会报错?
第二个疑问:这里又为啥会报错了?
字节码截图:为什么最后一个get方法会有一个checkcast指令啊?
背景知识:
我知道Java的泛型其实是一个语法糖,只在源码中存在,编译成功之后的class文件里面泛型就会被擦除掉。在class文件里面是不存在ArrayList这种类型的,只存在ArrayList这种类型。