大家好,我是Hunk。
今天实习生阿豪一脸懵逼的找到我说遇到了一个诡异问题,他说自己创建好的集合在执行添加元素操作时抛出了UnsupportedOperationException
异常。有经验的人光听到这个异常就大概知道是踩坑了。
接下来我们按照他所创建集合的方式,并结合代码示例,来具体讲解一下为啥他的操作不能正常执行,代码示例如下所示。
public static void main(String[] args) {
// 通过Arrays.asList,将数组转成集合
List<String> list = Arrays.asList("Lucy", "Lily");
list.add("Tom");
}
运行main
方法后,异常如下所示。
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at com.hunk.Test.main(Test.java:11)
之所以会抛出异常就是因为这个Arrays.asList()
方法导致的,不光执行添加元素操作会抛出异常,像list.clear()
、list.remove()
这些涉及修改集合的方法也会抛出相同的异常。
接下来我们进入Arrays.asList()
方法,看看它具体都做了些啥操作。
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
乍一看,好像也没啥问题,这不就是new
出来一个ArrayList
吗。很多人跟到了这一步就觉得没啥往下看的必要了。
这个时候特别想说一句非常经典的话:你以为你以为的就是你以为的?
跟着继续往下走,当点进ArrayList
的时候,咦~~~好像发现问题了!这个new
出来的ArrayList
并不是我们平时用的java.util.ArrayList
,而是Arrays
里面的一个内部类。
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;
}
…………
}
到这大家应该明白是咋回事了吧。然后我们再具体看下这个内部类,里面并没有我们前面所说的诸如add()
、clear()
、remove()
等方法。之所以执行上述方法会抛出UnsupportedOperationException
异常,是因为它继承的AbstractList
抛出的。
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
/**
* Sole constructor. (For invocation by subclass constructors, typically implicit.)
*/
protected AbstractList() {
}
public boolean add(E e) {
add(size(), e);
return true;
}
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
public void clear() {
removeRange(0, size());
}
……
}
可以看到在AbstractList
中涉及修改集合的操作,最终都会抛出异常。
其实这个问题在阿里的《Java开发手册》中也有明确的约定,而且是强制性的,如下所示。
至此,阿豪的问题就彻底分析清楚了,吃一堑长一智,以后就不要再往坑里跳了!

END
原文始发于微信公众号(Java浩窍门):Arrays.asList陷阱揭秘:集合操作禁地,小心踩坑!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/244520.html