293

我尝试将对象添加到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(未知来源)
    java.util.AbstractList.add(未知来源)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
4

8 回答 8

564

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

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

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

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

UnsupportedOperationException您可以通过阅读和的文档来了解这一点List.add(),其中将其记录为“(可选操作)”。该短语的确切含义在List文档顶部进行了解释。

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

seeAlso = new ArrayList<>(seeAlso);
于 2011-04-22T12:43:00.623 回答
11

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

通过对代码的最小更改,您可以执行以下操作将列表转换为 ArrayList。第一个解决方案对您的解决方案进行了最小的更改,但我猜第二个解决方案更优化。

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

或者

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = Stream.of(membersArray).collect(Collectors.toCollection(ArrayList::new));
于 2018-11-23T12:46:41.213 回答
5

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

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


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

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));
    }
}

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

@也可以看看

于 2018-12-12T08:20:06.300 回答
3

add如果您尝试通过以下方式List<T>返回, 您也会收到此异常Collections.singletonList(T o)

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

JVM 没有add()实现Collections.singletonList

于 2021-03-15T16:48:37.910 回答
2

列出 membersList = Arrays.asList(membersArray);

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

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

于 2018-10-23T05:45:47.100 回答
0

您必须初始化您的 List 另见:

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

或者

List<String> seeAlso = new ArrayList<String>();
于 2013-02-28T09:35:57.123 回答
-3

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

seeAlso.add(groupDn);

seeAlso 列表是不可修改的。

于 2011-04-22T12:43:48.630 回答
-4

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

{ seeAlso.addall(groupDn); }

add 添加单个项目,而 addAll 将集合中的每个项目逐个添加。最后,如果集合已被修改,这两种方法都会返回 true。在 ArrayList 的情况下,这是微不足道的,因为集合总是被修改,但如果要添加的项目已经存在,其他集合,例如 Set,可能会返回 false。

于 2019-06-17T12:31:40.963 回答