周围的同事都打错了,你真的理解了泛型了吗
今天和同事们日常batttle,聊到反射时,抛出一个问题~
使用集合类时我们通常会给类型约束,对于此对象会进行编译器检查,如果传入的是其他类型就会报错,如下
ArrayList<Integer> arrayList =new ArrayList<Integer>();
arrayList.add("111");
那么如果使用反射,是否可以绕过他的类型检查呢???? 是否可以成功调用???
这就是今天的问题 是否可以,并回答原因 !!!
下面看代码实测
//创建一个Integer类型的list
ArrayList<Integer> arrayList =new ArrayList<Integer>();
//获取它的add方法
Method add = arrayList.getClass().getDeclaredMethod("add",Integer.class);
//调用他的add方法
add.invoke(arrayList,111);
//打印数组元素查看结果
System.out.println(arrayList);
测试结果为:运行报错!!!!!
找不到add方法,必须当参数未Object.class时才能找到方法
换句话说,对于泛型类型,使用反射时Method方法只能获取基类 所以使用反射时无法做类型约束,要用反射 一定是 获得的基类作为参数的对象,由此得出结果,这是一个伪命题,使用反射时根本无法做类型约束!!!!
敲黑板【咣、咣、咣】
所以,当我们去使用反射调用泛型方法时,一定要注意转入的类型。一定要准守java的类型擦除规则,找到基类型,如下
- 所有参数化容器类都被擦除成非参数化的(raw type);如List、List<List>都被擦除成List;
- 所有参数化数组都被擦除成非参数化的数组;如List[],被擦除成List[];
- Raw type的容器类,被擦除成其自身,如List 被擦除成List;
- 原生类型(int,String还有wrapper类)都擦除成他们的自身;
- 参数类型E,被擦除成Object;
- 所有约束参数如<? Extends E>、都被擦除成E;
- 如果有多个约束,擦除成第一个,如<T extends Object & E>,则擦除成Object;