当前位置: 首页 > 知识库问答 >
问题:

为什么Java 8的可选不能用在论点中

宿丰
2023-03-14

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

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

许多网页指定可选的不应用作方法参数。考虑到这一点,我可以使用下面的方法签名并添加一个清晰的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的对象检索两个输入参数,然后调用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个答案

单于山
2023-03-14

哦,那些编码风格是需要加点盐的。

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

一般情况下:可选统一了两个状态,这两个状态必须被解开。因此更适合于结果而不是输入,因为数据流的复杂性。

 类似资料:
  • 当使用Java8类时,有两种方法可以将值包装到Optional中。 我理解是使用的唯一安全方法,但为什么?为什么不直接使用

  • 为了区分(a)任何值、(b)显式null和(c)无值的情况,我使用和注释。 这在Spring Boot 2.1.0/Jackson 2.9.7中非常适用。 目前(更新后)似乎像一样处理。它呈现,尽管该字段是用注释的。在Spring Boot 2.5.5/Jackson 2.12.5中,它呈现:

  • 在Java8中,可以返回而不是。Java8文档说,可选的是“一个容器对象,它可以包含非空值,也可以不包含非空值。如果存在一个值,isPresent()将返回true,而get()将返回该值。” 在实践中,这为什么有用呢?另外,有没有使用作为首选项的情况?那表演呢?

  • 我尝试样式复选框背景颜色,但它不会改变任何我做。我正在使用最新的火狐29。 是否在css中或浏览器中有一些规则更改? CSS: 下面是一个演示http://jsfidle.net/6kxrg/

  • 但是当我使用Java8时, 它抛出 java.time.format.DateTimeParseException:无法分析文本“201510”:无法从TemporalAccessor获取LocalDate:{Year=2015,MontHofYear=10},ISO类型为java.time.Format.Parsed

  • 假设我有一个非常简单的PHP CRUD系统来管理数据库。假设它有一个产品列表。使用Doctrine ORM,我想查询数据库并查看/编辑/添加记录。根据入门手册, 创建实体类时,所有字段都应该是受保护的或私有的(不是公共的),每个字段都有getter和setter方法(除了$id)。使用变异子可以让条令钩住调用,这些调用以一种如果直接使用entity#field=foo设置值就无法实现的方式操纵实体