关于 Arrays.asList add、remove 操作的 UnsupportedOperationException
来源:互联网 发布:昆明行知中学 编辑:程序博客网 时间:2024/06/05 20:46
以前在项目中遇到过这么一个问题,就是用Arrays.asList()将一个数组转换成list后,执行一些 add 、remove等操作时总是报UnsupportedOperationException错误,今天在看源码时才发现,原来Arrays.asList()这个方法转换后的list实现类不是我们常用的ArrayList,而是
一个Arrays的静态内部类,该类直接继承AbstractList类:
/** * @serial include */ 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; } }
注意,此类没有重写父类AbstractList的 add(E e)、remove(int index)方法,而父类的这两个方法体没有任何有意义的操作,只是抛了一个UnsupportedOperationException异常:
/** * Appends the specified element to the end of this list (optional * operation). * * <p>Lists that support this operation may place limitations on what * elements may be added to this list. In particular, some * lists will refuse to add null elements, and others will impose * restrictions on the type of elements that may be added. List * classes should clearly specify in their documentation any restrictions * on what elements may be added. * * <p>This implementation calls {@code add(size(), e)}. * * <p>Note that this implementation throws an * {@code UnsupportedOperationException} unless * {@link #add(int, Object) add(int, E)} is overridden. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) * @throws UnsupportedOperationException if the {@code add} operation * is not supported by this list * @throws ClassCastException if the class of the specified element * prevents it from being added to this list * @throws NullPointerException if the specified element is null and this * list does not permit null elements * @throws IllegalArgumentException if some property of this element * prevents it from being added to this list */ public boolean add(E e) { add(size(), e); //调用add(int index, E element)方法,此方法抛异常 return true; } /** * {@inheritDoc} * * <p>This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { throw new UnsupportedOperationException(); }/** * {@inheritDoc} * * <p>This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { throw new UnsupportedOperationException(); }
那为啥会这样呢,重写一下很麻烦吗?按理说,jdk开发者绝对不会这么粗心大意的,这样做毕竟有其道理,以下是个人猜想,估计八九不离十。
开发Arrays.asList这个方法,是将数组转换成list,以便Java开发者能用更习惯的方式来操作这些元素,而这个方法的意义,也仅限于操作这个数组本身,也就是转换后的list本质上还是对这个数组的引用,一切操作的都会直接作用于数组本身:
String[] strArr = {"aaa","ccc","bbb"}; List<String> li = Arrays.asList(strArr); Collections.reverse(li); //输出:bbb ccc aaa for(String str : strArr){ System.out.print(str+" "); } //li.set(1, "lll");
可以看到,我们对li进行反转操作的结果是strArr的元素同样也反转了
而如果重写add、remove会有啥后果?要知道,数组是长度固定的,add、remove等操作如果合法,要么原来数组的长度改变,这与数组长度固定矛盾,要么将list的数组引用到一个新的数组,这与Arrays.asList()设计初衷矛盾————故不能让其成为一个合法的操作。
最后留一个小问题,上面测试代码中的li.set(1, “ccc”)方法能正常执行吗,为什么?
最后附个小贴士:
如果想让Arrays.asList()生成的List与初始数组脱离关系,成为一个普通的java.util.ArrayList可以吗?当然可以!java.util.ArrayList类有一个重载的构造方法public ArrayList(Collection<? extends E> c)
,
此方法接收Collection实现类,把接收对象的数据拷贝一份作为自己的数据,而 Arrays.asList()生成的List当然也是Collection的实现类,所以可以直接入参:
List<String> li = Arrays.asList(strArr);ArrayList<String> mylist = new ArrayList<String>(li);
- 关于 Arrays.asList add、remove 操作的 UnsupportedOperationException
- Arrays.asList不能remove、add等,抛UnsupportedOperationException
- Arrays.asList的到的List进行remove操作报java.lang.UnsupportedOperationException
- 数组转换为List(Arrays.asList)后add或remove出现UnsupportedOperationException
- Arrays.asList() 得到 集合 执行 add() 和 remove() 抛 UnsupportedOperationException 异常
- 数组转换为List(Arrays.asList)后add或remove出现UnsupportedOperationException
- 数组转换为List(Arrays.asList)后add或remove出现UnsupportedOperationException
- Arrays.asList方法返回的List不能执行add、remove操作
- Arrays.asList() 返回的list不能add,remove
- Arrays.asList() 返回的list不能add,remove
- Arrays.asList()返回的List不能add和remove
- Arrays.asList()引起的java.lang.UnsupportedOperationException
- 关于Arrays的asList()
- 关于Arrays.asList()报java.lang.UnsupportedOperationException异常分析
- 为什么Java里的Arrays.asList不能用add和remove方法?
- 为什么Java里的Arrays.asList不能用add和remove方法?
- Arrays.asList() 返回的list不能add,remove以及慎用java.util.Collections.copy()方法
- Arrays.aslist新建的list集合不能add(),set(),remove()你知道吗?
- Codeforces Round #333 (Div. 1)
- HDU ACM 2138 How many prime numbers
- 1019. General Palindromic Number (20)
- Ubuntu 12.04 使用Eclipse搭建C/C++编译环境
- Android Studio——R文件小问题
- 关于 Arrays.asList add、remove 操作的 UnsupportedOperationException
- 10010---bean 的作用域:singleton;prototype;WEB 环境作用域
- vijos-p1002-过河
- 10011---使用外部属性文件
- [kuangbin带你飞]专题二 搜索进阶 I - A计划(HDU 2102)
- 1020. Tree Traversals (25) (重建二叉树)
- SQL Server 访问发送Http请求
- 2015 naver's Reading List
- 常用嵌入式文件系统介绍