小编典典

为什么不应该在参数中使用 Java 8 的 Optional

all

我在许多网站上阅读过 Optional 应该只用作返回类型,而不是在方法参数中使用。我正在努力寻找一个合乎逻辑的原因。例如,我有一段逻辑,它有 2
个可选参数。因此,我认为像这样编写我的方法签名是有意义的(解决方案 1):

public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
    // my logic
}

许多网页指定 Optional 不应用作方法参数。考虑到这一点,我可以使用以下方法签名并添加明确的 Javadoc
注释来指定参数可能为空,希望未来的维护人员会阅读 Javadoc,因此在使用参数之前始终执行空检查(解决方案 2) :

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

或者,我可以用四个公共方法替换我的方法,以提供更好的接口并使其更明显 p1 和 p2 是可选的(解决方案 3):

public int calculateSomething() {
    calculateSomething(null, null);
}

public int calculateSomething(String p1) {
    calculateSomething(p1, null);
}

public int calculateSomething(BigDecimal p2) {
    calculateSomething(null, p2);
}

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

现在我尝试编写类的代码,它为每种方法调用这段逻辑。我首先从另一个返回Optionals
的对象中检索两个输入参数,然后调用calculateSomething. 因此,如果使用解决方案 1,调用代码将如下所示:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);

如果使用解决方案 2,调用代码将如下所示:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

如果应用了解决方案 3,我可以使用上面的代码,或者我可以使用以下代码(但它的代码要多得多):

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p1, p2);
    } else {
        result = myObject.calculateSomething(p1);
    }
} else {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p2);
    } else {
        result = myObject.calculateSomething();
    }
}

所以我的问题是:为什么使用 s 作为方法参数被认为是不好的做法Optional(参见解决方案 1)?
对我来说,它看起来是最易读的解决方案,并且最明显的是,对于未来的维护者来说,参数可能是空的/null。(我知道设计者Optional打算将它仅用作返回类型,但我找不到在这种情况下不使用它的任何合乎逻辑的理由)。


阅读 152

收藏
2022-03-09

共1个答案

小编典典

哦,这些编码风格需要加点盐。

  1. (+) 将 Optional 结果传递给另一个方法,不进行任何语义分析;把它留给方法,很好。
  2. (-) 在方法内部使用导致条件逻辑的可选参数实际上是适得其反的。
  3. (-) 需要在 Optional 中打包参数,对于编译器来说是次优的,并且会进行不必要的包装。
  4. (-) 与可为空的参数相比,Optional 的成本更高。
  5. (-) 有人在实际参数中将 Optional 作为 null 传递的风险。

一般来说: Optional 统一了两个必须解开的状态。因此,对于数据流的复杂性,结果比输入更适合。

2022-03-09