zoukankan      html  css  js  c++  java
  • Java Arrays.asList 返回的集合执行iterator.remove报java.lang.UnsupportedOperationException问题

    最近在开发过程中遇到了数组需要转换成List并且需要在循环中剔除元素的操作,按照正常操作使用Arrays.asList()然后在获取其iterator在调用remove方法即可,但是实际操作中居然报了java.lang.UnsupportedOperationException,使用iterator的remove可以安全的删除元素,但是为什么使用了迭代器还会报这种错,看一下源码就焕然大悟了。

    先看看Arrays.asList方法的源码

        @SafeVarargs
        @SuppressWarnings("varargs")
        public static <T> List<T> asList(T... a) {
            return new ArrayList<>(a);
        }
    
    

    这里看源码乍一看返回的ArrayList,似乎也没啥问题,但是在跟进这个new ArrayList方法,可以发现,这是一个在Arrays.class下继承了AbstractList的内部类,并不是我们经常使用的java.util下的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) {
                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) {
                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;
            }
    
            @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) {
                E[] a = this.a;
                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;
            }
    
            @Override
            public boolean contains(Object o) {
                return indexOf(o) != -1;
            }
    
            @Override
            public Spliterator<E> spliterator() {
                return Spliterators.spliterator(a, Spliterator.ORDERED);
            }
    
            @Override
            public void forEach(Consumer<? super E> action) {
                Objects.requireNonNull(action);
                for (E e : a) {
                    action.accept(e);
                }
            }
    
            @Override
            public void replaceAll(UnaryOperator<E> operator) {
                Objects.requireNonNull(operator);
                E[] a = this.a;
                for (int i = 0; i < a.length; i++) {
                    a[i] = operator.apply(a[i]);
                }
            }
    
            @Override
            public void sort(Comparator<? super E> c) {
                Arrays.sort(a, c);
            }
        }
    

    仔细看这个内部类,它并没有重写iterator的remove方法,所以默认会使用了AbstractList中iterator的remove方法,跟踪AbstractList的迭代器类,可以发现AbstractList的remove方法

            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();
    
                try {
                    AbstractList.this.remove(lastRet);
                    if (lastRet < cursor)
                        cursor--;
                    lastRet = -1;
                    expectedModCount = modCount;
                } catch (IndexOutOfBoundsException e) {
                    throw new ConcurrentModificationException();
                }
            }
    

    这里可以看到,remove调用了AbstractList.this.remove()方法,那么AbstractList.this到底是啥呢,这里AbstractList.this实际上就是Arrays$ArrayList,兜兜转转又回到了自身,然后调用了Arrays$ArrayList的remove方法,Arrays$ArrayList并没有重写remove,所以又回到了AbstractList的remove的方法,然后可以看到AbstractList的remove方法直接就抛出了UnsupportedOperationException()

        public E remove(int index) {
            throw new UnsupportedOperationException();
        }
    
  • 相关阅读:
    解决:Could not resolve archetype org.apache.maven.archetypes
    Spring MVC配置MyBatis输出SQL
    Spring集成MyBatis 通用Mapper以及 pagehelper分页插件
    关于SpringMVC或Struts2接受参数接收不到的原因
    配置quartz启动时就执行一次
    ajaxFileUpload进行文件上传时,总是进入error
    spring mvc注入配置文件里的属性
    java中将一个文件夹下所有的文件压缩成一个文件
    flume failed to start agent because dependencies were not found in classpath
    ubuntu不能安装pip unable to install pip in unbuntu
  • 原文地址:https://www.cnblogs.com/mrmoo/p/9942418.html
Copyright © 2011-2022 走看看