使用Java中的Arrays.asList()报Exception in thread "main" java.lang.UnsupportedOperationException异常问题

使用Java中的Arrays工具类中的静态方法.asList(...)进行后续操作可能会出现 java.lang.UnsupportedOperationException异常问题

1、问题出现
比如以下例子:

    public static void main(String[] args) {
        String[] str = {"1","2","3","4"};
        List<String> list = Arrays.asList(str);
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            iterator.next();
            iterator.remove();
        }
    }

上例中通过Arrays.asList(str)获得一个list,然后我们利用一个迭代器对其中的元素进行删除操作,但是改代码会报如下错误:

2、错误分析
为什么会报这个错误呢?
我们来看一下Arrays.asList()的源码就知道了。

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

可以看出该静态方法实际上帮我们新建了一个ArrayList,并利用数组a初始化。目前来讲也没啥问题,那么我们继续深入......。去看看这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;
        }

从上面源码中可以看出,Arrays这个工具类实际上自己实现了一个内部类ArrayList,而不是调用我们熟知的java.util.ArrayList

虽然自己实现的这个内部类继承和java.util.ArrayList都是继承AbstractList,但是在AbstractList中的remove、add等方法在AbstractList中是默认throw UnsupportedOperationException,这时候就需要继承的子类重写该方法。

      public void add(int index, E element) {
          throw new UnsupportedOperationException();
      }
      /**
       * {@inheritDoc}
       *
       * <p>This implementation always throws an
       * {@code UnsupportedOperationException}.
       *
       * @throws UnsupportedOperationException {@inheritDoc}
       * @throws IndexOutOfBoundsException     {@inheritDoc}
       */
      public E remove(int index) {
          throw new UnsupportedOperationException();
      }

java.util.ArrayList重写了这些方法,而Arrays中自己新建的内部类ArrayList没有重写,所以会抛出异常。

3、解决问题
那么针对这种情况如何解决呢?可以参考以下方式:

public class Test {

    public static void main(String[] args) {
        String[] str = {"1","2","3","4"};
        //以下方式解决
        List<String> list = new ArrayList<>(Arrays.asList(str));
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            iterator.next();
            iterator.remove();
        }
    }
}

可以通过java.util.ArrayList构造方法直接初始化一个list。因为Arrays.asList(str)实际上返回了一个集合类型。我们可以想象成,str数组的每个元素依次弹出到list中,这种形象的比喻。

4、补充
贴一下java.util.ArrayList的其中一个构造函数源码:

posted @ 2020-07-18 19:06  fridays  阅读(397)  评论(0)    收藏  举报