Java List.add()UnsupportedOperationException

Java List.add() UnsupportedOperationException

我试图向List实例添加对象,但它抛出了UnsupportedOperationException。有人知道为什么吗?

我的Java代码:

1
2
3
4
5
6
7
8
9
10
11
12
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);
    }
}

错误消息:

1
2
3
4
5
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)

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

一个常见的例子是由Arrays.asList()返回的List:它被记录为不支持任何结构修改(即删除或添加元素)(emphasis mine):

Returns a fixed-size list backed by the specified array.

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

您可以通过阅读UnsupportedOperationExceptionList.add()的文档来了解这一点,这些文档将此文档记录为"(可选操作)"。这个短语的确切含义在List文档的顶部进行了解释。

作为一个解决方案,您可以创建一个列表副本到一个已知的可修改实现,如ArrayList

1
seeAlso = new ArrayList<>(seeAlso);


必须初始化列表,另请参见:

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

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


形成继承概念,如果当前类中的某些特定方法不可用,它将在超级类中搜索该方法。如果可用,则执行。

It executes AbstractList class add() method which throws UnsupportedOperationException.

当您从数组转换为集合obejct时。也就是说,基于数组的API将提供固定大小的集合对象,因为数组的行为是固定大小的。

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

用于构造的样品。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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)类。因此,它从继承中执行super AbstractListadd()函数,该函数抛出UnsupportedOperationException

由于AbstractList是一个抽象类,它向iterator() and listIterator()提供实现。所以,我们可以在列表对象上迭代。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.unmodifiableList(list);

样品来源:

1
2
3
4
5
6
7
public class Collections {
    public static <T> List<T> unmodifiableList(List<? extends T> list) {
        return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));
    }
}

Collection—有时称为容器—只是一个将多个元素组合成一个单元的对象。集合用于存储、检索、操作和通信聚合数据。

也见

  • hashmap vs哈希表
  • 对象序列化使用可序列化和可外部化的接口

许多列表实现支持对添加/删除和数组的有限支持。aslist(membersarray)就是其中之一。您需要在java.util.arraylist中插入记录,或者使用下面的方法转换为arraylist。

只需对代码进行最小的更改,就可以在下面将列表转换为arraylist。第一个解决方案是在您的解决方案中有一个最小的变化,但是第二个解决方案是更优化的,我想。

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

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

list memberslist=数组.aslist(membersarray);

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

new arraylist<>(arrays.aslist(membersarray));使其可变


不能修改LDAP查询的结果。您的问题在这一行:

1
seeAlso.add(groupDn);

SeeAlso列表不可修改。