温馨提示:阅读本文需要3-4分钟(少量代码)
今天,我们来解决一个问题:
人生一切难题,知识给你答案。
数组与集合都是用来存储对象的容器,两者之间可以进行相互转换,数组转集合可以通过Arrays.asList方法。
通过ArrayList.asList方法将数组转成集合后,能否修改集合个数?针对这个问题,我们直接给出例子:
public class Demo { public static void main(String[] args){ String[] strings={"A","B","C"}; List<String> stringList=Arrays.asList(strings); stringList.set(0,"G"); System.out.println(strings[0]); stringList.add("M"); } } 复制代码
运行结果:
G Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(AbstractList.java:148) at java.util.AbstractList.add(AbstractList.java:108) ... 复制代码
通过上面的例子可以发现通过set()方法修改元素的值,原有数组相应位置的值也被修改了,说明修改值没有问题,接着通过调用add()方法直接抛出UnsupportedOperationException异常,说明不能进行修改元素个数的任何操作。
那为什么不能修改元素个数呢?进入Arrays.asList源码中查看:
public static <T> List<T> asList(T... a) { return new ArrayList<>(a); } 复制代码
发现直接创建了一个ArrayList对象,按照我们平时对ArrayList的理解,应该可以修改元素个数啊?原来这个ArrayList不是我们平时使用的那个ArrayList,它是Arrays的静态内部类ArrayList。
public class Arrays { ... private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable{ private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); } @Override public int size() { return a.length; } @Override public Object[] toArray() { return a.clone(); } @Override @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { ... } @Override public E get(int index) { return a[index]; } @Override public E set(int index, E element) { E oldValue = a[index]; a[index] = element; return oldValue; } @Override public int indexOf(Object o) { ... } @Override public boolean contains(Object o) { ... } @Override public Spliterator<E> spliterator() { ... } @Override public void forEach(Consumer<? super E> action) { ... } @Override public void replaceAll(UnaryOperator<E> operator) { ... } @Override public void sort(Comparator<? super E> c) { ... } } ... } 复制代码
Arrays的静态内部类ArrayList中,set方法本质还是对数组进行值的修改操作,并且静态内部类ArrayList内部没有实现类似add、remove、clear相关方法,所以调用修改元素个数的相关方法时会抛出UnsupportedOperationException异常。
还有一个问题,我们在上面案例中通过set方法修改了ArrayList集合的第一个元素的值,在我们访问原有数组的第一个位置时,值也被改变了,这是为什么呢?
public class Arrays { ... private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable{ private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); } ... } ... } 复制代码
静态内部类ArrayList的成员变量a使用了final,用于存储集合的数组引用始终被强制指向原有数组。
因此,通过Arrays.asList方法将数组转换成集合后,避免修改元素的个数,否则会引发异常。