【问题标题】:Return multiple values from a Java method: why no n-tuple objects?从 Java 方法返回多个值:为什么没有 n 元组对象?
【发布时间】:2011-11-20 05:09:59
【问题描述】:

为什么没有一个(标准的、Java 认证的)解决方案,作为 Java 语言本身的一部分,从 Java 方法返回多个值,而不是开发人员必须使用自己的方法,例如 Maps、Lists、对等?为什么 Java 不支持 n 元组对象?

特别是考虑可能同时修改两个对象(串联)的琐碎私有方法,在这种情况下,将类型对象作为返回听起来有点过头了。

【问题讨论】:

  • 嗯......?使用这样的数据结构标准,不是吗?
  • 当然,因为没有人完成采用这些自定义解决方案之一并将其标准化的工作!
  • 有一个标准的方式:它被称为一个对象。
  • 是的,这些是标准的数据结构,但没有办法将其作为语言结构的一部分而不是将其包装在集合中吗?如果可以的话,一个简单的类比是,您可以通过两种方式将多个参数传递给一个方法:(a).有一个参数变量是 List> 并从中提取单个参数或 (b)。每个参数都有不同的参数变量。只是大声思考......
  • 您尝试做的是非标准的。标准方法包括使用地图、列表或自定义对象!

标签: java methods return-type


【解决方案1】:

我假设 OP 的意思是“为什么 Java 不支持 n 元组对象?”。 Python、Haskell、Lisp、ML 等具有异构的 n 元组功能。通常,在一种语言中明显返回多个对象的能力是语法糖(即在 python 中返回'a','b')。

原因当然是语言设计和一致性。 Java 喜欢非常明确,不喜欢匿名数据结构(尽管我希望我们有匿名闭包)。

例如在 Java 中,没有办法说我想要一个接受这些类型参数并返回它的回调。有些人认为这是一个巨大的弱点,其他人则喜欢一致性和明确性。

恕我直言,虽然这很烦人,但我经常通过制作静态内联类来解决这个问题:

private static class Combo {
   String name;
   int weight;
}

是的,这很乏味,但后来我经常重用和重构这些类,使它们成为顶级并添加行为。事实上,走这条路的好处之一是添加新字段更容易,其中匿名数据结构(如在 FP 语言中)添加字段变得更加困难(您最终会更改大量代码)。

我应该注意,对于 2 元组,有些人使用(或滥用)java.util.Map.Entry,因为在 Java 6 中有一个 java.util.AbstractMap.SimpleEntry。现在还有一些人使用 Commons Lang3's Pair support (2-tuple)

Scala 通过某种欺骗方式支持 n 元组,并且拥有一大堆 2-16 个元组接口,这些接口在语言中是标准的,并且在语法上对程序员隐藏。

出于纯粹的教育原因,您可能希望了解其他languages accomplish this

更新:适用于 Java 8

Java 8 将/可能(所以这是我的电话号码......也许可以打电话给我)支持一个名为 java.lang.BiValue 的接口,您可以使用一个名为 java.lang.BiVal 的具体实现。这些类是为了帮助支持新的 lambda 功能。但请注意,这仅适用于 2 元组。

更新:2015 年

Java 8 没有获得对元组的支持。

更新:作者 2015 年

如果您仍然希望支持元组,那么有三个库可以很好地支持元组:

  • javatuples - 支持 JDK 5 及更高版本。最多 10 个元组。
  • JOOλ - 来自 jOOQ 的作者,但需要 JDK 8。
  • Commons Lang 3 - 现在支持三元组(3 元组)并支持 JDK 6 及更高版本。

【讨论】:

  • Map.Entry 是我的最爱。为什么要为其他语言即时执行的简单任务创建命名对象?
  • 这种模式可能存在并发问题(安全发布)。 this answer to a similar questionfinal + 构造函数)中描述的模式应该可以解决这个问题。
  • 是的,我只是为了简洁起见,而不是为了完全重用。不可变对象总是一个不错的选择。
  • 如果我必须返回 3 个对象怎么办?
  • +1 用于在不断变化的条件下返回并实际更新答案。我希望更多的人这样做。
【解决方案2】:

Java 方法只返回零或一个值; java 的标准。如果您需要返回多个值,请创建一个包含多个值的对象并返回它。

【讨论】:

  • 唯一的问题是,对于一个非常琐碎(私有)的方法,有时听起来有点矫枉过正......
  • void 是java中的返回类型,顺便说一句。
  • @The Elite Gentleman 说到这里你也可以 throw null 这意味着 null 必须是一个异常:)
  • 这不是“为什么它不存在”问题的答案
  • “为什么没有”这个问题和“猴子怎么样?”一样有意义。这是一个愚蠢的问题。 java没有多个返回值。
【解决方案3】:

如果要返回两个对象,通常希望返回封装这两个对象的单个对象。

【讨论】:

    【解决方案4】:

    有很多骇人听闻的方法来实现这一点,一种方法是返回一个Object[],但是你需要担心索引和空指针检查,这会变得很糟糕。另一种方法是返回一个String,但是你必须解析它,它变得很讨厌。

    我认为真正的问题是为什么?

    这就是问题所在 - 如果我和你一起做一个项目,并且我看到了这种类型的行为,我会重写它,这样你就可以看到应该如何处理它。如果你提供代码示例,我会重写它来说明。

    编写具有单一职责的方法,如果它们需要返回的数据超出其能力,您可能应该使用一个对象,或者将其分解为更小的方法。

    【讨论】:

    • 单一责任的好论据
    • 使用对象并分解成更小的方法是非常好的方法,如答案中所述。
    • @Travis 假设我们有一个磁盘缓存对象,该对象具有一个返回缓存值及其注释(例如上次修改时间)的方法。多个返回值比使用包装器对象要干净得多。我们不能使用两个方法调用,因为缓存可以在方法调用之间改变。
    • @fhucho 这是一个适用的情况,这是有道理的。您正在寻找的是最后一次写入及其详细信息/元数据。为什么不应该将它封装在一个对象中?
    • @Travis 我认为这会导致代码更清晰、更容易理解。此外,不需要包装类。但我想这是一个见仁见智的问题。
    【解决方案5】:

    因为不推荐从方法返回多个值(在 Java 中)。

    如果你需要一个方法中不相关的值,你需要一个不同的数据结构,比如包含这些值的对象。如果您需要同一类的多个实例(即几个 Strings ),您需要根据您的需要返回一个数组或一些集合。

    在其他语言(例如 Go)中返回多个值用于返回错误代码,但 Java 使用异常的设计不同。

    【讨论】:

      【解决方案6】:

      有一种新的模式可用,并且符合您在 JavaScript 等语言中可能看到的“全异步”特性。

      现在我的很多代码都是这样的:-)

      public class Class1 {
      
          public interface Callback {
             void setData(String item1, String item2);
          }
          public void getThing(Callback callback) {
              callback.setData("a", "b");
          }
      }
      
      public class Class2 {
      
          public void doWithThing(Class1 o) {
              o.getThing(new Class1.Callback() {
                  public void setData(String item1, String item2) {
                      ... do something with item 1 and item 2 ...
                  }
              });
          }
      
      }
      

      没有要创建的新对象,也没有太多额外的类,因为接口是对象的内部类。

      这就是 Swift 如此出色的原因。代码可能如下所示:

      o.getThing({ item1, item2 -> Void in
          ... do something with item 1 and item 2 ...
      });
      

      而且由于唯一的参数是块,即使这样:

      o.getThing { item1, item2 -> Void in
          ... do something with item 1 and item 2 ...
      };
      

      Java 需要努力使包含回调的代码更易于阅读。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-02
        • 1970-01-01
        • 2020-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-15
        • 2013-05-27
        相关资源
        最近更新 更多