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

嵌套可选。get在orElse()中选中并链接时生成警告

呼延骏俊
2023-03-14

我刚刚偶然发现了一个由IntelliJ生成的警告,我想知道,我是错过了什么,还是IntelliJ只是忽略了下面or子句的右侧?

示例代码:

  Random random = new Random();
  public void test(){
    Optional<String> a = Optional.ofNullable(random.nextInt(10)>5?"something":null);
    Optional<String> b = Optional.ofNullable(random.nextInt(10)>5?"something":null);
    if(a.isPresent() || b.isPresent()){
      log.info(a.orElse(b.get()));
    }
  }

警告是可选的。没有“isPresent()”检查的get()'显示在b上。get()。我知道or是以一种惰性的方式从左到右计算的,但我假设无论是a还是b都必须有一个值,因为它在if中被显式检查。

这是IntelliJ静态代码分析中的错误吗?

共有2个答案

呼延卓
2023-03-14

我知道or是以一种懒惰的方式从左到右计算的

是的,这意味着如果a.isPresent()返回true,b.isPresent()将不会被计算,并且无论如何条件都将为true。此时您的b.get()将在b.isPresent()为false时抛出异常

由于您正在进一步使用a.orElse,您可以简单地检查b.isPresent()是否为空,因为如果a为空,orElse不会引发异常。所以

if(b.isPresent()){
  log.info(a.orElse(b.get()));
}

不应该发出警告。

(我假设这是一个玩具示例,因此我不会进一步评论这里正在发生的滥用可选)

商同化
2023-03-14

是的|短路,但orElse没有短路,因此如果不存在b,即使存在a,get仍会运行并引发异常。这就是为什么Java提供了orElseGet,如果我们确实需要运行“else”部分,它需要调用一个供应商(即零参数函数)。

log.info(a.orElseGet(() -> b.get()));

现在,我在这台电脑上没有IntelliJ,但我怀疑它仍然会抱怨。静态分析引擎(可能)不理解orElseGet和|之间的交互。通常,当我遇到这样的情况时,我会将有问题的代码分解成一个单独的函数。

void onFirst<T>(Optional<T> first, Optional<T> second, Consumer<T> consumer) {
  if (first.isPresent()) {
    consumer.accept(first.get());
  } else if (second.isPresent()) {
    consumer.accept(second.get());
  }
}

// Then call as
onFirst(a, b, (value) -> log.info(value));

有点冗长,但它通过了静态分析集合。额外的冗长在一个可以重用的单独帮助函数中消失了。

 类似资料:
  • 我一直在使用Java 8中的新的可选类型,我遇到了一个似乎不受功能支持的常见操作:“orelseoptional” 请考虑以下模式: 这种模式有很多种形式,但归结起来就是在一个可选项上需要一个“orelse”,该“orelse”接受一个函数,生成一个新的可选项,只有当当前的可选项不存在时才调用。 它的实现如下所示: 我很好奇这样一种方法不存在的原因,如果我只是在一种无意的方式下使用Optional

  • 问题内容: 我最近在Swift中进行了大量编程。今天,当出现问题时,我在JavaScipt中做了一些工作: 是否有类似于JavaScript中的可选链接的内容?一种防止没有任何变量的方法? 例: 将失败一半的时间,因为有时返回未定义。 我能想到的唯一解决方案是一个函数: 我希望能够执行以下操作: 仅在返回对象后才执行问号后的部分。 但这不是很精巧。有更好的东西吗?运营商的神奇组合? 编辑 我知道我

  • 问题内容: 所以我正在与Optionals一起工作,并且遇到了一种奇怪的行为。我想知道这是否真的是意向性的“功能”或其他…奇特的… 这是给定的示例:我有一个带有Optional的方法,在其中我要评估另一个Optional的方法。如果其他Optional不存在,我将引发IllegalArgumentException: 现在,如果the 为空的Optional,即使存在,它也会引发IllegalAr

  • 问题内容: Java中是否有一种优雅的流式处理方式,可以说“如果此Optional映射到具有计算值的另一个Optional,如果该值存在,则返回一个空的Optional”? 我想到了类似的东西: 但这是不可能的。 我想出的解决方案有些冗长,而不像流式: 问题答案: 您不需要以下子句:

  • 我想检查Adapter类的值,它是Device类中的嵌套对象,如下所示: 插座看起来像: 适配器看起来像: 如果为空,则为字段名设置默认值。 我的方法如下: 看起来,它可以工作,但IntelliJ抱怨setter部分是无效的: 带有一条消息: 这里出现的问题是,在这种情况下,是否可以将空类型强制转换为可选,以便类型相互兼容或以不同的方式设置默认名称。

  • 为什么这段代码会抛出异常?为什么它还要去“奥雷尔斯”分店? 这是因为某种怪异的处决令吗?那么在计算orElse分支之前没有设置第一个可选项的值?