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

Java 可选和 orElse

Java 可选和 orElse

qq_笑_17 2023-06-21 16:17:44
我是 Java 选项的新手,但我看到另一个开发人员编写的代码,但我不明白:String t = null;Optional.ofNullable("notnull")    .orElse(        Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))    );为什么这段代码会抛出异常?为什么它甚至会转到“orElse”分支?这是因为一些奇怪的执行顺序吗?那么在评估 orElse 分支之前没有设置第一个可选值?
查看完整描述

7 回答

?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

永远不会调用流orElse,但会执行方法本身。这意味着方法参数也传递给它。Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))因此无论传递给第一次调用的值如何,都会调用该部分Optional.ofNullable。


如果你不希望这种情况发生,你需要传递Supplier这样的信息:


String t = null;

Optional.ofNullable("notnull")

    .orElseGet(

        () -> Optional.ofNullable(t).orElseThrow(() -> new RuntimeException("MyException"))

    );

orElseGet只有在调用流时才会调用供应商。请注意,您需要一个RuntimeException而不是已检查的异常才能脱离供应商。


查看完整回答
反对 回复 2023-06-21
?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

那是因为里面的代码orElse()总是会被评估。换句话说,即使您指定非空,它也会被执行Optional,所以这就是Exception抛出的原因。

如果您查看Java 可选 – orElse() 与 orElseGet()orElse()文章的部分,您可以在他们的示例中看到这一点,其中显示:

我们可以很容易地推断出 orElse() 的参数即使在具有非空 Optional 的情况下也会被评估。


查看完整回答
反对 回复 2023-06-21
?
慕妹3146593

TA贡献1820条经验 获得超9个赞

我真的很想知道为什么这段代码是以这种方式编写的。似乎它需要触发一个异常,并在可选中添加一个显式的 NULL 值。


正如已经说过的,当使用orElse()而不是orElseGet()方法时,无论 T 的值如何(例如Optional<T>)都会被评估。


我会使用更好的时尚和理解:


String value = "notnull"; // could be null

Optional.ofNullable(value)

    .orElseThrow(MyException::new);

如果值为 NULL,则会触发异常。


注意:您可以使用方法引用来调用异常


查看完整回答
反对 回复 2023-06-21
?
largeQ

TA贡献2039条经验 获得超7个赞

你写的是这样的:


String t = null;

String myException = Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"));

Optional.ofNullable("notnull").orElse(myException);

在您知道您的值是否为空之前,部分已被评估。如果您想要评估,请考虑orElse方法。Optional"Lazy"orElseGet


查看完整回答
反对 回复 2023-06-21
?
胡说叔叔

TA贡献1804条经验 获得超8个赞

关于Optional ,您应该注意以下几点:

  1. 如果已知被包装的值是否为空,请使用Optional.of()或Optional.empty()。如果不确定(例如值是从其他地方获得的变量),请使用Optional.ofNullable()

  2. Optional.orElse()和Optional.orElseGet()之间有一个重要的区别。

    1. orElse接受一个已经计算出的值,如果提供了一个表达式,它会立即执行并立即计算。这发生在有问题的代码中。因此,这个 else 变体应该用于已经可用的值或原语。

    2. orElseGet接受一个供应商函数,该函数仅在评估可选链并请求替代值时运行。当替代值的生成或计算成本昂贵时应使用此方法。

// Fine

Optional<String> name = Optional.of(someValue).orElse("defaultName");


// But this:

Optional<String> name = Optional.of(someValue).orElse(db.queryName());


// Is better written as following, as it saves you from an expensive operation

Optional<String> name = Optional.of(someValue).orElseGet(() -> db.queryName());


查看完整回答
反对 回复 2023-06-21
?
慕丝7291255

TA贡献1859条经验 获得超6个赞

问题是按执行顺序。它尝试计算 .orElse(...) 的值并在 .orElseThrow 上抛出 MyException。

换句话说,如果 t 不为空,执行流程如下:

1) 计算值

Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))

2) 使用 (1) 中的值

Optional.ofNullable("notnull").orElse(...)


查看完整回答
反对 回复 2023-06-21
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

结果是预料之中的,因为在 Java 中,在调用带有参数的方法之前,JVM 之前所做的事情是评估参数值。
那就是调用的参数值.orElse()

Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))

由于t引用null,因此预计会抛出异常。


查看完整回答
反对 回复 2023-06-21
  • 7 回答
  • 0 关注
  • 208 浏览

添加回答

举报

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