java泛型的类型擦除几个问题

tech2024-07-30  63

写ArrayList源码学习笔记(3)的时候发现了ArrayList因为泛型擦除而导致元素存储使用的是Object数组。

然后又了解到泛型出现之后存在类型转换的问题,所以研究了java泛型的逆变、协变&不变。

后来又想到几个问题如下:

(1)java为什么要做类型擦除?

(2)java是如何做的类型擦除?

(3)类型擦除之后,是怎么在后续使用过程中识别类型的?

于是搜到了这两篇文章解决了疑惑:Java 泛型,你了解类型擦除吗?   知乎问答

(1)了解到的原因是为了做兼容,引入泛型之后不会对当前的逻辑造成影响,只需要对泛型进行特殊扩展即可。

(2)java代码编译后,只保留了其基础类型,泛型类型以另外的字段记录在class文件中。

(3)因为记录在class文件里,总有办法能读取出来。

意外收获:虽然泛型能控制add参数的类型,但是反射依然是能将不同类型的元素加入到list里的,来自第一篇文章的一个例子

public class ToolTest { public static void main(String[] args) { List<Integer> ls = new ArrayList<>(); ls.add(23); // ls.add("text"); try { Method method = ls.getClass().getDeclaredMethod("add",Object.class); method.invoke(ls,"test"); method.invoke(ls,42.9f); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } for ( Object o: ls){ System.out.println(o); } } }

打印结果是:

23 test 42.9

 

最新回复(0)