为啥Java里的Arrays.asList不能用add和remove方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥Java里的Arrays.asList不能用add和remove方法相关的知识,希望对你有一定的参考价值。

简单的说:  因为Arrays.asList 返回的List,其实是一个只读的List

详细解释: Arrays.asList方法返回的ArrayList是继承自AbstractList.

AbstractList中  add,set,remove的方法内容如下

public void add(int index, E element)   //添加元素
    throw new UnsupportedOperationException(); //抛出异常 
  
  
public E set(int index, E element)   //修改元素
    throw new UnsupportedOperationException();//抛出异常  
  
  
public E remove(int index)   //删除元素
    throw new UnsupportedOperationException(); //抛出异常 

解决办法:

1: 如果要把数组转成集合,并且可以进行"增删改"的话, 可以使用for/whlie循环的方式, 把数组的元素挨个添加到集合.

2: 把Arrays.List的返回值作为参数, 来构造1个新集合 . 这个新集合就可以进行"增删改"了

import java.util.*;
public class Test 
public static void main(String[] args) 
String[] ss = "A","B","C";
List<String> list = new ArrayList<>(Arrays.asList(ss));  
list.add("D");//增
list.remove(0);//删
list.set(2,"H");//改
System.out.println(list);//输出[B, C, H]

参考技术A



主要内部使用的是 java.util.Arrays.ArrayList 而不是 java.util.ArrayList



而这个类 ,没有实现 add和remove  方法


    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;
        
    

为什么Java里的Arrays.asList不能用add和remove方法?

在平时的开发过程中,我们知道能够将一个Array的对象转化为List。这种操作,我们仅仅要採用Arrays.asList这种方法即可了。笔者前段时间一直用这种方法,有一天,我发现通过Arrays.asList得到的List无法进行add和remove等操作。


以下是一段非常easy的測试代码:  

    public class MainFacade {
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1,2,3);
            list.add(5);
            System.out.print(list.toString());
        }
    }

只是上面的代码会throw出一个UnsupportedOperationException这种异常  

Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(AbstractList.java:148) at java.util.AbstractList.add(AbstractList.java:108) at org.popkit.MainFacade.main(MainFacade.java:14) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

终其原因是Arrays.asList方法返回的ArrayList是继承自AbstractList同一时候实现
了RandomAccess和Serializable接口。定义例如以下:  

    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable

我们再来看看AbstractList这个类的定义:  

    public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> 

这时我们发现AbstractList这个类的set add remove方法定义例如以下:

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

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

    public E remove(int index) {
        throw new UnsupportedOperationException();
    }
如今知道了它throw UnsupportedOperationException异常的原因了。

 

通过上面的分析,我们知道。事实上通过asList方法得到的List是仅仅读的。那么平时我们如何避免这种发生错误?我们能够採用例如以下方法:  

    List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3));




















以上是关于为啥Java里的Arrays.asList不能用add和remove方法的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Arrays.asList() 返回自己的 ArrayList 实现

为啥直接将 Arrays.asList() 分配给 var 时会出现 AssertionError?

Java Arrays.asList

Arrays.asList()用法梳理

java Arrays.asList

JAVA数组与List相互转换