当可选值为空时如何返回?

2022-09-01 01:30:44

我喜欢现在Java标准库中的可选选项。但是有一个基本问题我一直遇到,我还没有想出如何以最好的方式解决(最容易阅读和理解,最漂亮,最短):

当可选值为空时,如何从方法返回?

我正在寻找一种通用解决方案,适用于可选数量和代码块大小的不同组合。

在以下示例中,我将尝试显示我的意思:

void m1() {
    // When I get an optional:
    Optional<String> o = getOptional();

    // And want to return if it's empty
    if (!o.isPresent()) return;
    
    // In the whole rest of the method I have to call Optional.get 
    // every time I want the value:
    System.out.println(o.get());
    
    // Which is pretty ugly and verbose!
}


void m2() {
    // If I instead return null if a value is absent:
    String s = getNullabe();
    if (s == null) return;
    
    // Then I can use the value directly:
    System.out.println(s);
}

这个问题是关于如何获得上述两个示例的良好方面:可选类型的安全类型和可空类型的简洁性。

其余示例对此进行了更多说明。

void m3() {
    // If I on the other hand want to throw on empty that's pretty and compact:
    String s = getOptional()
        .orElseThrow(IllegalStateException::new);
    
    System.out.println(s);
}

void m4() {
    Optional<String> o = getOptional();
    if (!o.isPresent()) return;
    
    // I can of course declare a new variable for the un-optionalised string:
    String s = o.get();

    System.out.println(s);
    
    // But the old variable still remains in scope for the whole method 
    // which is ugly and annoying.
    System.out.println(o.get());
}


void m5() {
    // This is compact and maybe pretty in some ways:
    getOptional().ifPresent(s -> {
        System.out.println(s);

        // But the extra level of nesting is annoying and it feels 
        // wrong to write all the code in a big lambda.
        
        getOtherOptional().ifPresent(i -> {
            // Also, more optional values makes it really weird and 
            // pretty hard to read,  while with nullables I would 
            // get no extra nesting, it would looks good and be 
            // easy to read.
            System.out.println("i: " + i);
            
            // It doesn't work in all cases either way.
        });
    });
}


Optional<String> getOptional() {
    throw new UnsupportedOperationException();
}

Optional<Integer> getOtherOptional() {
    throw new UnsupportedOperationException();
}

String getNullabe() {
    throw new UnsupportedOperationException();
}

如果可选值为空,我该如何从方法返回,而不必在方法的其余部分使用,而无需声明额外的变量,也没有额外的块嵌套级别?get

或者,如果不可能获得所有这些,那么处理这种情况的最佳方法是什么?


答案 1

您可以使用 :orElse(null)

String o = getOptional().orElse(null);
if (o == null) {
    return;
}

答案 2

你可以使用和方法来代替,如果函数是无效的,你需要做副作用,你可以使用,ifPresentmapifPresent

optional.ifPresent(System.out::println); 

如果另一个方法返回依赖于 Optional than,则该方法可能还需要返回一个 Optional 并使用 map 方法

Optional<Integer> getLength(){
    Optional<String> hi = Optional.of("hi");
    return hi.map(String::length)
}

大多数时候,当您呼叫和时,您正在滥用。isPresentgetOptional


推荐