请各位大师帮我分析一下这是为什么会出现如下的现象

[code="java"]
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;

public class BaiduDemo05 {

public static void main(String[] args) throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    ArrayList<Integer> collection1 = new ArrayList<Integer>();
    collection1.getClass().getMethod("add", Object.class).invoke(collection1, "abc");
    System.out.println(collection1.get(0));//ABC

    ArrayList<String> collection2 = new ArrayList<String>();
    collection2.getClass().getMethod("add", Object.class).invoke(collection2, "abc");
    System.out.println(collection2.get(0));//ABC

    ArrayList collection22 = new ArrayList();
    collection22.getClass().getMethod("add", Object.class).invoke(collection22, "abc");
    System.out.println(collection22.get(0));//ABC

    ArrayList<Long> collection3 = new ArrayList<Long>();
    collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc");
    System.out.println(collection3.get(0));//ABC

    ArrayList<Date> collection4 = new ArrayList<Date>();
    collection4.getClass().getMethod("add", Object.class).invoke(collection4, 1);
    System.out.println(collection4.get(0));//ABC
}

}
[/code]
但是在将abc替换为1时,只有第2个,也就是collection2会出现异常,求解释,谢谢大师。

至于“类型擦除”:
[code="java"] ArrayList collection2 = new ArrayList();

collection2.getClass().getMethod("add", Object.class).invoke(collection2, 1);

System.out.println(collection2.get(0));//ABC

[/code]

编译后相当于:
[code="java"]
ArrayList collection2 = new ArrayList(); //这里是擦除了
collection2.getClass().getMethod("add", Object.class).invoke(collection2, 1);

System.out.println((String)collection2.get(0));//因为 PrintStream有对应的println(String s)的方法,所以会有强制类型转化。

[/code]

ArrayList collection2 = new ArrayList();
这个泛型是String啊!
collection2.getClass().getMethod("add", Object.class).invoke(collection2, 1);

肯定错了,你应该把ArrayList<[b]Integer[/b]> collection2 = new ArrayList();

ArrayList collection2 = new ArrayList();
这个泛型是String啊!
collection2.getClass().getMethod("add", Object.class).invoke(collection2, 1);
肯定错了,你应该把ArrayList collection2 = new ArrayList();改为ArrayList collection2 = new ArrayList()

反射出来的是不带泛型的,所以可以把字符串放进List,同理,取出来也都是Object类型,打印的话,自动调用toString,所以看到abc

问题出在System.out.println方法上,查看PrintStream类,发现它的println方法有如下几种:
[code="java"]
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
[/code]

[code="java"]
public void println(Object x) {
synchronized (this) {
print(x);
newLine();
}
}
[/code]

。。。其他的就不列举了。
ArrayList collection2 = new ArrayList();
collection2 声明的泛型是String,所以调用collection2.get(0)时,编译器认为它返回的是String 类型对象,所以println方法应该是调用第一种,如果你往collection2 中add是整数1,取回来的就是Integer对象,那么就会发生类型转换错误。至于为什么能用反射方法往collection2 中加入1,我想你应该知道的,不然不会写出这样的例子,挺有意思的。

System.out.println(collection2.get(0))需要对泛型进行检查,但反射不检查泛型,你add方法是通过反射用的,get方法也应该可以通过反射用:
ArrayList collection2 = new ArrayList();
collection2.getClass().getMethod("add", Object.class).invoke(collection2, 1);
//System.out.println(collection2.get(0));//ABC

Object obj1 = collection2.getClass().getMethod("get", int.class).invoke(collection2, 0);
System.out.println(obj1);

或者这样也行:
ArrayList collection2 = new ArrayList();
collection2.getClass().getMethod("add", Object.class).invoke(collection2, 1);
Object object = collection2.get(0);
System.out.println(object);//ABC

总之就是想办法跳过println(String x)的泛型检查就行了。

很明显,无解。。

ArrayList collection4 = new ArrayList();
collection4.getClass().getMethod("add", Object.class).invoke(collection4, 1);
这个直接打印就不做泛型检查了?这个是不报错的。就String的通不过,费解!!!

这个打印调用的是println(Object x)方法,Date是Object的子类能通过检查。

[quote]那为什么下面的Date,将abc换成1后也不报错呢[/quote]
因为Date调用的是public void println(Object x) ,是以Object类型来打印的,不需要类型转换。