Java List.add()UnsupportedOperationException

时间:2011-04-22 12:39:45

标签: java list exception arraylist unsupportedoperation

我尝试将对象添加到List<String>实例,但它会抛出UnsupportedOperationException。 有谁知道为什么?

我的Java代码:

String[] membersArray = request.getParameterValues('members');
List<String> membersList = Arrays.asList(membersArray);

for (String member : membersList) {
    Person person = Dao.findByName(member);
    List<String> seeAlso;
    seeAlso = person.getSeeAlso();
    if (!seeAlso.contains(groupDn)){
        seeAlso.add(groupDn);
        person.setSeeAlso(seeAlso);
    }
}

错误消息:

java.lang.UnsupportedOperationException
    java.util.AbstractList.add(Unknown Source)
    java.util.AbstractList.add(Unknown Source)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

8 个答案:

答案 0 :(得分:358)

并非每个List实现都支持add()方法。

一个常见示例是Arrays.asList()返回的List:记录以支持任何结构修改(即删除或添加元素)(强调我的):< / p>

  

返回由指定数组支持的固定大小列表。

即使这不是您尝试修改的特定List,答案仍然适用于其他List实现,这些实现是不可变的或仅允许某些选定的更改。

您可以通过阅读UnsupportedOperationExceptionList.add()的文档来了解相关信息,该文档将此文档记录为“(可选操作)”。 List文档的顶部解释了这个短语的确切含义。

作为一种解决方法,您可以将列表副本创建为ArrayList等已知可修改的实现:

seeAlso = new ArrayList<>(seeAlso);

答案 1 :(得分:3)

您必须初始化List seeAlso:

List<String> seeAlso = new Vector<String>();

List<String> seeAlso = new ArrayList<String>();

答案 2 :(得分:1)

许多List实现支持有限的添加/删除支持,而Arrays.asList(membersArray)就是其中之一。您需要将记录插入到java.util.ArrayList中,或使用以下方法转换为ArrayList。

在代码中进行最小的更改,您可以执行以下操作以将列表转换为ArrayList。我猜第一种解决方案的更改最少,但是第二种解决方案更优化。

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = new ArrayList<>(Arrays.asList(membersArray));

OR

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = Stream.of(membersArray).collect(Collectors.toCollection(ArrayList::new));

答案 3 :(得分:1)

形成继承概念,如果当前类中没有某些垂直方法,它将在超类中搜索该方法。如果可用,它将执行。

  

它执行 AbstractList<E> add() 方法,该方法抛出UnsupportedOperationException


从数组转换为集合对象时。即基于数组的API到基于集合的API,那么它将为您提供固定大小的集合对象,因为数组的行为具有固定大小。

  

java.util.Arrays.asList(T ... a)

提取样品以进行构象。

public class Arrays {
    public static <T> List<T> asList(T... a) {
        return new java.util.Arrays.ArrayList.ArrayList<>(a); // Arrays Inner Class ArrayList
    }
    //...
    private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {
        //...
    }
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    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();
    }

    public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        //...
    }

    public ListIterator<E> listIterator() {
        return listIterator(0);
    }
    private class ListItr extends Itr implements ListIterator<E> {
        //...
    }
}

在上述源代码中,您可能会发现java.util.Arrays.ArrayList类不是@Override add(index, element), set(index, element), remove(index)。因此,从继承中,它执行超级AbstractList<E>add()函数,该函数抛出UnsupportedOperationException

由于AbstractList<E>是一个抽象类,它为iterator() and listIterator()提供了实现。因此,我们可以遍历列表对象。

List<String> list_of_Arrays = Arrays.asList(new String[] { "a", "b" ,"c"});

try {
    list_of_Arrays.add("Yashwanth.M");
} catch(java.lang.UnsupportedOperationException e) {
    System.out.println("List Interface executes AbstractList add() fucntion which throws UnsupportedOperationException.");
}
System.out.println("Arrays → List : " + list_of_Arrays);

Iterator<String> iterator = list_of_Arrays.iterator();
while (iterator.hasNext()) System.out.println("Iteration : " + iterator.next() );

ListIterator<String> listIterator = list_of_Arrays.listIterator();
while (listIterator.hasNext())    System.out.println("Forward  iteration : " + listIterator.next() );
while(listIterator.hasPrevious()) System.out.println("Backward iteration : " + listIterator.previous());

您甚至可以创建固定大小的数组表单Collections类Collections.unmodifiableList(list);

样本来源:

public class Collections {
    public static <T> List<T> unmodifiableList(List<? extends T> list) {
        return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));
    }
}

Collection(有时也称为容器)只是将多个元素组合为一个单元的对象。集合用于存储,检索,操作和传达聚合数据。

@另请参见

答案 4 :(得分:0)

我们可以使用addall()而不是使用add()

{ seeAlso.addall(groupDn); }

add仅添加一个项目,而addAll则一个接一个地添加集合中的每个项目。最后,如果对集合进行了修改,则这两个方法均返回true。对于ArrayList来说,这是微不足道的,因为该集合始终会被修改,但是如果要添加的项已经存在,则其他集合(例如Set)可能会返回false。

答案 5 :(得分:0)

如果您尝试对 Collections.singletonList(T o) 返回的 add 进行 List<T>,您也会收到此异常:

<块引用>

返回一个仅包含指定对象的不可变列表。返回的列表是可序列化的。

JVM 没有为 add() 实现 Collections.singletonList

答案 6 :(得分:-1)

列表memberList = Arrays.asList(membersArray);

返回不可变列表,您需要做的是

新ArrayList <>(Arrays.asList(membersArray));使其可变

答案 7 :(得分:-3)

您无法修改LDAP查询的结果。你的问题就在这一行:

seeAlso.add(groupDn);

seeAlso列表是不可修改的。