为了账号安全,请及时绑定邮箱和手机立即绑定

为什么不能在参数中使用Java 8的可选性?

为什么不能在参数中使用Java 8的可选性?

慕标5832272 2019-07-15 09:53:23
为什么不能在参数中使用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个赞

哦,那些编码风格要用一点盐。

  1. (+)将一个可选的结果传递给另一个方法,而不进行任何语义分析;将该结果留给该方法是很好的。
  2. (-)使用可选参数导致方法中的条件逻辑实际上是相反的。
  3. (-)需要将参数打包到可选中,对于编译器来说不是最优的,并且需要进行不必要的包装。
  4. (-)与可空参数相比,可选参数的开销更大。

一般情况下:可选统一了两个州,这两个州必须拆解。因此,结果比输入更适合于数据流的复杂性。


查看完整回答
反对 回复 2019-07-15
?
米琪卡哇伊

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);



查看完整回答
反对 回复 2019-07-15
  • 3 回答
  • 0 关注
  • 647 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信