美文网首页
说说ArrayList参数为Collection

说说ArrayList参数为Collection

作者: M_lear | 来源:发表于2022-01-29 23:53 被阅读0次

ArrayList只提供了这一个构造函数可以在初始化时添加元素:

构造函数.png

其中,引人注意的点是
c.toArray()其实已经拷贝了一遍c中的元素了,如果elementData的类型不为Object[],还需要再拷贝一遍。等于说拷贝了两遍。

下面这个例子,integerArray的元素1,2,3就需要拷贝两次:

Integer[] integerArray = {1, 2, 3};
List<Integer> list = new ArrayList<>(Arrays.asList(integerArray));

为什么会造成拷贝两次的这种尴尬局面,我认为是java不支持真正的泛型的缘故,如果java支持真正的泛型,可以直接把elementData的类型声明为E[]而非Object[],ArrayList只能添加E及其子类型元素,这样的话直接elementData = c.toArray()就够用了。

但由于java是伪泛型,ArrayList<Integer>泛型擦除后等价于ArrayList<Object>,我们可以通过反射给ArrayList添加任意类型的元素,所以这就需要ArrayList的实际存储结构必须是Object[]数组,否则就有可能因为类型不匹配报java.lang.ArrayStoreException。

类似于这样:

Integer[] a = {1, 2, 3};
Object[] b = a;
b[1] = new Object();

结果:

image.png

附录

反射为ArrayList<Integer>添加一个String类型元素:

ArrayList<Integer> list = new ArrayList<>();
Class klass = list.getClass();
Method add = klass.getMethod("add", Object.class);
add.invoke(list, "String");
System.out.println(list);

debug一下这个代码:

Integer[] integerArray = {1, 2, 3};
List list = new ArrayList<>(Arrays.asList(integerArray));
debug.png

最终elementData是一个Object[3]数组,数组元素依然还是Integer,因为都是浅拷贝。

相关文章

网友评论

      本文标题:说说ArrayList参数为Collection

      本文链接:https://www.haomeiwen.com/subject/rpefkrtx.html