【问题标题】:Unmodifiable List in javajava中不可修改的列表
【发布时间】:2013-04-27 16:46:31
【问题描述】:

我正在尝试设置一个不可修改的List

在我的代码中,我有一个返回列表的方法。

这个列表不应该被修改,但我不想捕获 unmodifiableList 返回的异常。

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

这是一个现有代码,我必须对其进行转换以返回一个不可修改的列表,但如果调用了“add”方法,则不必捕获任何异常。

首先我创建了一个类,它实现了 List 来覆盖“add”方法来记录异常而不是捕获它。

但我不知道如何正确实例化它...

【问题讨论】:

  • 很难理解您给出的代码 sn-p 因为它似乎部分在方法中,部分不在方法中。也不清楚您所说的“我不想捕获异常”是什么意思 - 哪个异常?你真的是说你想要一个默默地忽略任何修改它的尝试的列表吗?咳!
  • 使用 collections 包,不要重新发明轮子。
  • 当您执行 oListeRet = listeReferenceSelectAll 时,您将丢失对您创建的数组列表的引用。我怀疑这不是你想要的。
  • @LumpN:我还是觉得不对劲。如果您调用 add 并且它没有失败,但它也没有将项目添加到列表中,这听起来像是灾难的秘诀。

标签: java list arraylist unmodifiable


【解决方案1】:

你需要java.util.Collections:

return Collections.unmodifiableList(oListeRet);

如果您必须自己编写,请让该类实现List 接口并为修改内容的方法抛出异常。

【讨论】:

    【解决方案2】:

    Collections.unmodifiableList

    返回指定列表的不可修改视图。这种方法允许 模块为用户提供对内部列表的“只读”访问权限。 对返回列表的查询操作“通读”到指定 列表,并尝试修改返回的列表,无论是直接还是通过 它的迭代器,导致 UnsupportedOperationException。返回的 如果指定的列表是可序列化的,则列表将是可序列化的。 同样,返回的列表将实现 RandomAccess,如果 指定的列表可以。

    【讨论】:

      【解决方案3】:

      Java-9提供了一种新的方法来创建unmodifiable/immutableList

      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 创建一个包含任意数量元素的不可变列表。

      【讨论】:

      • 他明确表示不想抛出异常
      【解决方案4】:

      虽然接受的答案解决了省略/吞下UnsupportedOperationException 的要求,但应该解释为什么这是一种不受欢迎的做法。

      1) 吞下异常的总体意图与“快速失败”原则相矛盾。他们没有及早发现和发现缺陷,而是被允许“躲在地毯下”变成定时炸弹。

      2) 不投掷UnsupportedOperationException 直接违反了List 的合同,该合同规定:

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

      因此,问题标题中所写内容的正确答案:“Java 中的不可修改列表”仍应为:

      return Collections.unmodifiableList(oListeRet);
      

      【讨论】:

        【解决方案5】:

        如果您绝对必须这样做,请尝试遵循您正在创建的列表中 java.util.List 指定的约定。

        你的代码看起来像

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

        在同一行添加您需要的更多方法。只需确保代码中可能用于修改的所有构造函数和方法都被覆盖,以确保列表不可修改。

        使用 Collections API 是一种更简洁、更好的方式,因此只有在使用 Collections.UnmodifiableList 不能满足您的需要时才使用这种方式。

        请记住,调试时这将是一场噩梦,因此请尽可能多地记录。

        【讨论】:

        • @user2346325 当所有其他人列出正确的“官方”方法时,你不能认真接受这个答案!
        • @SeanPatrickFloyd - 我同意这是一种非常肮脏的做法,所以我在答案的结尾再次提到了使用 Collections API,因为它是一种标准的做法,并使用只有在别无他法的情况下才采用这种方法。
        • 所以你打算通过添加更多错误代码来使问题复杂化?并请指出“不良影响”?那些比添加更多错误代码更有害的方法是什么?
        • 通过这样做,您将在代码中希望add 方法起作用的任何地方引入隐藏的错误。在原始帖子中有一个关于记录异常的声明。如果您计划迁移代码,那么记录异常将帮助您找到需要更新的地方。如果您不打算记录尝试修改列表并稍后更正这些代码行的实例......那么我不建议默默地忽略从列表中添加/删除元素的请求!
        • 这不是正确的做法,请考虑使用 Collections.unmodifiableList
        【解决方案6】:

        1) 这些行没有意义

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

        2) 使用 Collections.unmodifiableList。

        return Collections.unmodifiableList(oListeRet);
        

        你不需要捕获它可能抛出的异常,它们都是 UnsupportedOperationException - RuntimeExceptions

        【讨论】:

          【解决方案7】:

          关于不可修改列表的 cmets 是正确的。创建一个调用 Collections.unmodifiableList 的方法访问器。但是,您可能只想使用这样的数组,并在内部使用列表。

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

          【讨论】:

          • 在 Java 中转换数组几乎从不工作,也不能以所需的方式解决问题。
          猜你喜欢
          • 2010-12-15
          • 2010-12-20
          • 2018-01-02
          • 1970-01-01
          • 1970-01-01
          • 2011-02-04
          • 2011-04-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多