为什么不能在参数中使用Java 8的可选性?我在许多网站上阅读过,可选的应该仅作为返回类型使用,而不是在方法参数中使用。我很难找到合理的理由。例如,我有一个逻辑,它有两个可选的参数。因此,我认为这样写我的方法签名(解决方案1)是有意义的:public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
// my logic}许多网页指定的可选参数不应用作方法参数。考虑到这一点,我可以使用以下方法签名并添加一个清晰的Javadoc注释来指定参数可能为null,希望未来的维护人员能够读取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然后,我调用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();
}}所以我的问题是:为什么使用它被认为是不好的做法?Optionals作为方法参数(参见解决方案1)?在我看来,这是最容易读懂的解决方案,而且最明显的是,对于未来的维护人员来说,参数可能是空/空的。(我知道设计师们Optional只打算作为返回类型使用,但我找不到任何逻辑上的理由不使用它在这个场景中)。
3 回答
呼啦一阵风
TA贡献1802条经验 获得超6个赞
(+)将一个可选的结果传递给另一个方法,而不进行任何语义分析;将该结果留给该方法是很好的。 (-)使用可选参数导致方法中的条件逻辑实际上是相反的。 (-)需要将参数打包到可选中,对于编译器来说不是最优的,并且需要进行不必要的包装。 (-)与可空参数相比,可选参数的开销更大。
米琪卡哇伊
TA贡献1998条经验 获得超6个赞
虽然考虑可选的方法参数不是强制性的,但与其他可能的替代方案相比,这样的解决方案显得微不足道。为了说明这个问题,请检查以下构造函数声明: public SystemMessage(String title, String content, Optional<Attachment> attachment) { // assigning field values}
乍一看,这可能是一个正确的设计决策。毕竟,我们显式地将附件参数标记为可选参数。但是,对于调用构造函数,客户端代码可能会变得有点笨拙。 SystemMessage withoutAttachment = new SystemMessage("title", "content", Optional.empty()); Attachment attachment = new Attachment(); SystemMessage withAttachment = new SystemMessage("title", "content", Optional.ofNullable(attachment));
可选类的工厂方法没有提供清晰性,而只是分散了读者的注意力。注意,只有一个可选参数,但假设有两个或三个参数。鲍勃叔叔肯定不会为这样的代码?感到骄傲 当一种方法可以接受可选参数时,最好采用行之有效的方法,并使用方法过载来设计这种情况。
在SystemMessage类的示例中,声明两个单独的构造函数优于使用可选构造函数。 public SystemMessage(String title, String content) { this(title, content, null);}public SystemMessage(String title, String content, Attachment attachment) { // assigning field values}
这种更改使客户端代码更简单、更易于阅读。 SystemMessage withoutAttachment = new SystemMessage("title", "content"); Attachment attachment = new Attachment();SystemMessage withAttachment = new SystemMessage("title", "content", attachment);
添加回答
举报
0/150
提交
取消