这么简单的问题我都答错了,你真的了解泛型吗

230 阅读2分钟

周围的同事都打错了,你真的理解了泛型了吗

今天和同事们日常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;