简体   繁体   English

java中的不可修改列表

[英]Unmodifiable List in java

I'm trying to set a List unmodifiable.我正在尝试设置一个不可修改的List

In my code, I have a method which returns a list.在我的代码中,我有一个返回列表的方法。

This list shouldn't be modified, but I don't want to catch the exception returned by the unmodifiableList.不应修改此列表,但我不想捕获 unmodifiableList 返回的异常。

private List<T> listeReferenceSelectAll = null;
List<T> oListeRet = new ArrayList<T>();
oListeRet = listeReferenceSelectAll;
return new ArrayList<T>(oListeRet);

It is an existing code and I have to transform it to return an unmodifiable list, but if an "add" method has been called, no exception has to be caught.这是一个现有代码,我必须将其转换为返回一个不可修改的列表,但是如果调用了“add”方法,则不必捕获异常。

First I have create a class which implements List to override "add" method to log the exception and not to catch it.首先,我创建了一个实现 List 的类来覆盖“add”方法来记录异常而不是捕获它。

But I don't know how to correctly instantiate it...但我不知道如何正确实例化它...

You need java.util.Collections :你需要java.util.Collections

return Collections.unmodifiableList(oListeRet);

If you have to write your own, have that class implement the List interface and throw exceptions for the methods that modify contents.如果您必须自己编写,请让该类实现List接口并为修改内容的方法抛出异常。

Collections.unmodifiableList Collections.unmodifiableList

Returns an unmodifiable view of the specified list.返回指定列表的不可修改视图。 This method allows modules to provide users with "read-only" access to internal lists.这种方法允许模块为用户提供对内部列表的“只读”访问。 Query operations on the returned list "read through" to the specified list, and attempts to modify the returned list, whether direct or via its iterator, result in an UnsupportedOperationException.对返回列表的查询操作“通读”到指定列表,并尝试修改返回的列表,无论是直接还是通过其迭代器,都会导致 UnsupportedOperationException。 The returned list will be serializable if the specified list is serializable.如果指定的列表是可序列化的,则返回的列表将是可序列化的。 Similarly, the returned list will implement RandomAccess if the specified list does.类似地,如果指定的列表实现了,则返回的列表将实现 RandomAccess。

Java-9 provides a new methods to create unmodifiable/immutable List : Java-9提供了一种创建不可修改/不可变List的新方法:

jshell> List<Integer> list = List.of(1,2,3);
list ==> [1, 2, 3]

jshell> list.add(10);
|  java.lang.UnsupportedOperationException thrown: 
|        at ImmutableCollections.uoe (ImmutableCollections.java:70)
|        at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:76)
|        at (#6:1)

List.of creates an immutable list containing an arbitrary number of elements. List.of创建一个包含任意数量元素的不可变列表。

Although the accepted answer addresses the request of omitting / swallowing the UnsupportedOperationException , there should be an explanation of why it's an undesirable practice.虽然接受的答案解决了省略/吞下UnsupportedOperationException的请求,但应该解释为什么这是一种不受欢迎的做法。

1) The overall intent to swallow an exception is a contradiction of the "fail-fast" principle. 1)吞下异常的总体意图与“快速失败”原则相矛盾。 Instead of finding and catching defects early they are just allowed to go "under the carpet" turning into time bombs.他们没有及早发现和发现缺陷,而是被允许进入“地毯下”,变成定时炸弹。

2) Not throwing UnsupportedOperationException is a direct violation of List 's contract which says: 2) 不抛出UnsupportedOperationException是对List契约的直接违反,它说:

Throws:
    UnsupportedOperationException - if the add method is not supported by this list.

So the proper answer to what is written in the question's title: "Unmodifiable List in java" should still be:因此,对问题标题中所写内容的正确答案:“Java 中的不可修改列表”应该仍然是:

return Collections.unmodifiableList(oListeRet);

If you absolutely must do this, try to follow the contract specified by java.util.List in the list you are creating.如果您绝对必须这样做,请尝试遵循您正在创建的列表中的 java.util.List指定的约定。

Your code would look something like你的代码看起来像

public class UnmodifiableArrayList<E>  extends ArrayList<E> {

    public UnmodifiableArrayList(Collection<? extends E> c) {
        super(c);
    }

    public boolean add(int index) {
        return false;//Returning false as the element cannot be added 
    }

    public boolean addAll(Collection<? extends E> c) {
        return false;//Returning false as the element cannot be added 
    }

    public E remove(int index) {
        return null;//Returning null as the element cannot be removed
    }
}

Add any more methods you need on the same lines.在同一行上添加您需要的更多方法。 Just ensure that all the constructors and methods that might by used to modify in your code are overriden , so as to ensure the list is unmodifiable.只需确保您的代码中可能用于修改的所有构造函数和方法都被覆盖,以确保列表不可修改。

Using the Collections API is the cleaner and better way to do it, so use this way only if using Collections.UnmodifiableList does not satisfy your need.使用 Collections API 是一种更简洁、更好的方法,因此仅当使用 Collections.UnmodifiableList 不能满足您的需求时才使用这种方式。

And keep in mind this will be a nightmare while debugging so log as much as possible.请记住,这将是调试时的噩梦,因此请尽可能多地记录。

1) These lines make no sense 1)这些行没有意义

List<T> oListeRet = new ArrayList<T>();
oListeRet = listeReferenceSelectAll;

2) Use Collections.unmodifiableList. 2) 使用 Collections.unmodifiableList。

return Collections.unmodifiableList(oListeRet);

You dont need to catch exception it may throw, they are all UnsupportedOperationException - RuntimeExceptions您不需要捕获它可能抛出的异常,它们都是 UnsupportedOperationException - RuntimeExceptions

The comments about unmodifiable list are correct.关于不可修改列表的评论是正确的。 Make a method accessor that calls Collections.unmodifiableList.创建一个调用 Collections.unmodifiableList 的方法访问器。 However, you may want to just use an array like so, and use a list internally.但是,您可能只想使用这样的数组,并在内部使用列表。

 public MyObject[] getObjects() {
    return (MyObject[]) mList.toArray();
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM