我在很多网站上都读过 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
}
现在我尝试编写类的代码,为每种方法调用这段逻辑。我首先从另一个返回 Optional
s 的对象中检索两个输入参数,然后调用 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();
}
}
所以我的问题是:为什么使用 Optional
s 作为方法参数被认为是不好的做法(参见解决方案 1)? 对我来说,它看起来是最易读的解决方案,并且最明显的是,对于未来的维护者来说,参数可能为空/空。 (我知道 Optional
的设计者打算将它仅用作返回类型,但我找不到任何合乎逻辑的理由不在这种情况下使用它)。
原文由 Neil Stevens 发布,翻译遵循 CC BY-SA 4.0 许可协议
哦,那些编码风格要加一点盐。
一般来说:Optional 统一了两个状态,这两个状态必须被分解。因此,由于数据流的复杂性,结果比输入更适合。