当前位置: 首页 > 面试题库 >

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

艾自强
2023-03-14
问题内容

我已经在许多网站上阅读了Optional应该仅用作返回类型,而不能在方法参数中使用。我正在努力寻找一个合理的理由。例如,我有一段逻辑,其中包含2个可选参数。因此,我认为这样写我的方法签名(解决方案1)会很有意义:

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

许多指定为Optional的网页不应用作方法参数。考虑到这一点,我可以使用以下方法签名并添加清晰的Javadoc注释以指定参数可以为null,希望将来的维护者将读取Javadoc,因此始终在使用参数之前进行null检查(解决方案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();
    }
}

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


问题答案:

这些编码风格需要花些力气。

  1. (+)将Optional结果传递给另一种方法,而无需任何语义分析;将其留给方法,是完全可以的。
  2. (-)使用可选参数在方法内部引起条件逻辑实际上是相反的。
  3. (-)需要将参数打包在Optional中,对于编译器而言不是最佳选择,并且不需要进行包装。
  4. (-)与可为空的参数相比,可选的成本更高。

通常:Optional统一了两个状态,必须对其进行详细说明。因此,对于数据流的复杂性,比输入更适合结果。



 类似资料:
  • 如果我编写了ToIntFunction接口,我希望在接口中编码这样一个事实,即它只是一个返回原始int的函数,如下所示: 我想知道,Java8 API设计者选择将原始的替代方案与函数完全分离,是不是有一个令人信服的原因?是否有证据显示他们曾考虑这样做,并决定不这样做?我想类似的问题至少也会出现在其他一些“特殊”功能接口上,比如Consumer(可能是function )和Supplier(func

  • 问题内容: 我有一个sqlhelper类,其中包含一个重载的ExecuteNonQuery:一个仅包含一个参数(commandText),另一个仅包含两个参数(commandText,SqlParameter [])。 假设我有一个没有用户交互的独立控制台应用程序,并且我将调用一个存储过程,该存储过程将仅使用3个参数更新一个表,如果我可以轻松地构建字符串并使用SqlParameter[],有什么好

  • 假设您有一个简单的代码块,如下所示: 这个函数有两个参数和,分别表示请求和响应对象。 另一方面,还有其他函数带有第三个参数,称为。例如,让我们看看下面的代码: 我不明白的意义是什么,也不明白为什么要使用它。在那个例子中,如果id不存在,实际上在做什么?

  • 我发现Java 8没有与ZonedDateTime等价的功能,而是只与时间(ZonedTime类或类似的东西)一起工作。我知道他们包括OffsetTime类,但它只存储偏移量。 将时区与日期和时间一起存储,而不仅仅是存储偏移量,有助于更轻松地处理夏令时。 我不是要你给我选择,我知道有很多方法;我只是想知道为什么这样的类不包括在内,这是一个设计问题吗?或者他们只是发现它是多余的?

  • 现在使用Lambda表达式,为什么Java不能允许以下两个,因为它清楚地区分了这两个:

  • 我正试图用BlueJ完成一项为uni完成的任务,但我在第一个障碍上遇到了障碍。 在赋值中,我们得到了一个类,以及该类的构造函数、方法和参数的名称。我们不允许更改这些,因为赋值部分地由测试单元标记(或类似的东西)。 该类的一个构造函数如下所示 我已经(部分)完成了 我不明白的是为什么-为什么他们使用作为构造函数的参数?这样做有什么好处? (我想这样做肯定有好处(如果没有,功能就不会存在),但我不明白