Arrays.asList() 得到 集合 执行 add() 和 remove() 抛 UnsupportedOperationException 异常

本文深入探讨了使用Java中Arrays.asList()方法创建固定大小列表的过程,揭示了为何此方法返回的列表无法执行add()和remove()操作,并解析了其背后的实现原理。
通过 Arrays.asList() 得到集合
对这个集合进行 add() 和 remove() 操作
抛出java.lang.UnsupportedOperationException异常


直接根据 甲骨文官方的api 解释 入手
static <T> List<T> asList(T... a)
Returns a fixed-size list backed by the specified array.


很清晰 
该方法 返回由指定数组支持的固定大小的列表


再从源码入手


public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}


可以发现 该方法最终返回一个 ArrayList (注意,问题就是在这个地方引起的)


这个 ArrayList 不是我们 常用的那个 java.util.ArrayList


在源码中发现


在 Arrays 中 内部维护了一个内部类 ArrayList 


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) {
            if (array==null)
                throw new NullPointerException();
   a = array;
}


public int size() {
   return a.length;
}


public Object[] toArray() {
   return a.clone();
}


public <T> T[] toArray(T[] a) {
   int size = size();
   if (a.length < size)
return Arrays.copyOf(this.a, size,
    (Class<? extends T[]>) a.getClass());
   System.arraycopy(this.a, 0, a, 0, size);
   if (a.length > size)
a[size] = null;
   return a;
}


public E get(int index) {
   return a[index];
}


public E set(int index, E element) {
   E oldValue = a[index];
   a[index] = element;
   return oldValue;
}


        public int indexOf(Object o) {
            if (o==null) {
                for (int i=0; i<a.length; i++)
                    if (a[i]==null)
                        return i;
            } else {
                for (int i=0; i<a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }


        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }
    }

可以看出来 该 ArrayList 是继承了 AbstractList 在该 ArrayList 内部没有重写 add() 和 remove() 方法
所以在执行这俩个方法的时候 他是直接调用父类的


public boolean add(E e) {
add(size(), e);
return true;
}


public void add(int index, E element) {
throw new UnsupportedOperationException();
}


public E remove(int index) {
throw new UnsupportedOperationException();
}


到此为止 所以的谜团都已经解开了。
<think>嗯,用户问的是为什么用Arrays.asList()转换后的集合调用add/remove/clear方法会UnsupportedOperationException异常。首先,我得回忆一下Arrays.asList()的工作原理。这个方法返回的是一个固定大小的列表,底层其实是基于原数组的。所以这个列表不支持结构上的修改,比如添加或删除元素,因为这些操作会改变列表的大小,而数组的大小是固定的。 接下来,我需要确认这个返回的列表具体是什么类型的。我记得ArraysasList方法返回的是其内部的一个ArrayList类,但这个类并不是java.util.ArrayList,而是Arrays类的静态内部类。这个内部类没有覆盖addremove等方法,所以当调用这些方法时,实际上调用的是AbstractList的默认实现,而这些默认实现会UnsupportedOperationException异常。 然后,用户可能需要知道如何解决这个问题。也就是说,如果他们需要一个可修改的集合,应该怎么做。这时候应该建议他们使用new ArrayList<>(Arrays.asList(array)),这样会创建一个新的java.util.ArrayList,从而支持所有的修改操作。 另外,可能还需要解释为什么这样的设计存在。因为Arrays.asList()的设计初衷是为了提供一个轻量级的列表视图,避免数组数据的复制,从而提高效率。因此,它保留了数组固定大小的特性,不允许结构修改。 最后,用户可能没有意识到返回的列表标准ArrayList的区别,所以需要明确说明两者不同的实现类,以及这种设计导致的限制。同时,可能还要提醒其他需要注意的地方,比如如果修改数组元素,列表中的元素也会跟着变,因为列表是直接基于数组的。 总结起来,回答的结构应该是先说明现象,再解释原因,接着给出解决方案,最后可能补充相关的注意事项。然后按照用户的要求,生成相关问题,这些问题应该围绕Arrays.asList()的限制、替代方法、内部实现等展开。</think><< 当使用`Arrays.asList()`将数组转换为集合时,返回的集合是一个**固定大小**的列表视图,底层由原始数组支持。因此,调用`add()`、`remove()`、`clear()`等会改变集合结构的方法时,会出`UnsupportedOperationException`异常。以下是详细解释: ### 原因分析 1. **底层实现限制** `Arrays.asList()`返回的是`Arrays`内部类`ArrayList`(非`java.util.ArrayList`),它是一个基于数组的包装类,未实现修改集合的方法。 ```java // 示例代码 List<String> list = Arrays.asList("A", "B", "C"); list.add("D"); // UnsupportedOperationException ``` 2. **数组固定性** 数组的长度是固定的,而`add/remove/clear`等操作会尝试改变集合大小,这与数组的固定长度特性冲突,因此被禁止。 ### 解决方法 如果需要可修改的集合,可以显式创建新的`ArrayList`: ```java List<String> mutableList = new ArrayList<>(Arrays.asList("A", "B", "C")); mutableList.add("D"); // 正常执行 ``` ### 注意事项 - 即使通过`Arrays.asList()`获得的集合是固定大小的,仍可通过`set()`方法修改元素值,因为它不会改变集合大小。 - 对原始数组的修改会同步到集合中(二者共享存储空间)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值