【问题标题】:Return list or modify by reference返回列表或引用修改
【发布时间】:2013-11-21 00:46:14
【问题描述】:

在 java 中,我有一个修改列表内容的方法。是不是更好用:

public List modifyList(List originalList) { // note - my real method uses generics
     // iterate over originalList and modify elements
     return originalList;
}

还是做以下更好:

public void modifyList(List originalList) {
      // iterate over originalList and modify elements
      // since java objects are handled by reference, the originalList will be modified
      // even though the originalList is not explicitly returned by the method
}

注意 - 这两种方法的唯一区别是返回类型(一个函数返回 void,另一个返回 List)。

【问题讨论】:

  • 这主要是见仁见智。一方面返回列表可以允许方法链接。但它也混淆了方法签名。有点相关:Benefits and drawbacks of method chaining and a possibility to replace all void return parameters by the object itself
  • @RichardTingle - 我同意这有点主观,但我想知道是否有一个很好的论据反对一个选项或另一个可能会使我的代码在未来更难维护。
  • 你想要方法链吗?如果不是,那么第二个肯定会更好,因为它不会使您看起来像将 originalList 纯粹用作输入而不是修改它
  • 在您定义“更好”之前,此问题纯属意见。

标签: java


【解决方案1】:

这完全取决于您如何使用 List - 如果您正在实现某种列表并且这是您的 List 类的非静态方法,那么您应该编写

public List modifyList() // returning list

public int modifyList() // number of elements changed

如果是这个类之外的方法

关于对 List 或其副本执行操作:您应该考虑期望的行为和您的期望 - 最重要的是 - 我需要“旧”列表副本吗?。深拷贝列表可能有点开销。浅拷贝将无法在不影响“旧”列表的情况下对列表的某些元素执行操作(即更改其属性 - 如果它们是对象)。

关于返回 void:最好返回已更改列表(或至少已更改元素的数量),这将允许您链接方法调用,如果不需要,您可以随时忽略它。

【讨论】:

    【解决方案2】:

    如果你只是在操纵列表,那完全取决于气质。有些人(包括我)会争辩说使用第一个选项更容易阅读代码(如果你想要那种东西,它允许像 Adam 指出的那样进行链接)。

    但是,请记住,它并不是真正传入的引用。它实际上是一个指针。因此,如果您出于某种原因重新初始化 originalList 实例,例如放置一个

    originalList = new ArrayList();
    

    在你的方法体中。这不会影响您实际传递给方法的列表。

    【讨论】:

      【解决方案3】:

      在我看来,您应该只鼓励使用不可变类进行方法链接。

      如果你的函数改变了一个对象,那么在方法链中很容易意外地做到这一点。

      【讨论】:

        【解决方案4】:

        选项 1 的一个可能好处是它可以接受 null 列表。例如,如果您正在收集 Foos,并且通常创建一个全新的列表,但希望将 选项 添加到 现有 列表中。例如(请注意方法名称)

        public List<Foo> appendFoos(List<Foo> in) {
          if (in == null)
            in = new ArrayList<Foo>;
        
          // now go do it, e.g.
          in.add(someFooIFound);
        
          return in;
        }
        

        如果您愿意,还可以添加一个显式的无参数“get”方法

        public List<Foo> getFoos() {
           return appendFoos(null);
        }
        

        现在,在选项 #2 中,您可以让用户创建一个新的空 ArrayList 并将其传入,但选项 #1 更方便。即

        选项 1 用法:

        List<Foo> theFoos = getFoos();
        

        选项 2 用法:

        List<Foo> theFoos = new ArrayList<Foo>();
        appendFoos(theFoos);
        

        【讨论】:

          【解决方案5】:

          由于List 是可变的,所以第二种方法更好。您无需返回修改后的List

          【讨论】:

          • 如果你用Collections#unmodifiableList(List)装饰它就不会。
          猜你喜欢
          • 2011-04-08
          • 2014-09-21
          • 2017-03-23
          • 2011-04-20
          • 1970-01-01
          • 2014-08-24
          • 2019-12-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多