简体   繁体   English

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

[英]How to return when an optional is empty?

I love that optionals are in the Java standard library now. 我喜欢自选是在Java标准库现在。 But there is one basic problem I keep running into which I haven't figured out how to solve in the best (easiest to read and understand, prettiest, shortest) way: 但是我仍然遇到一个基本问题,我还没有弄清楚如何以最好的方式解决(最容易阅读和理解,最漂亮,最短)的方式:

How to return from a method when an optional is empty? 当可选项为空时如何从方法返回?

I am looking for a general solution which works for different combinations of numbers of optionals and sizes of code blocks. 我正在寻找一个通用的解决方案,适用于选项数和代码块大小的不同组合。

In the following examples I'll try to show what I mean: 在下面的例子中,我将尝试展示我的意思:

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);
}

This question is about how to get the good aspect of both the examples above: The type safely of the optional and the brevity of nullable types. 这个问题是关于如何获得上述两个例子的好方面:可选的安全类型和可空类型的简洁性。

The rest of the examples illustrates this more. 其余的例子更多地说明了这一点。

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();
}

How can I return from a method if an optional is empty, without having to use get in the rest of the method, without declaring an extra variable and without extra levels of block nesting? 如果可选项为空,如何在不声明额外变量且没有额外级别的块嵌套的情况下在方法的其余部分中使用get ,我如何从方法返回?

Or if it's not possible to get all that, what is the best way to handle this situation? 或者,如果不可能得到所有这些,那么处理这种情况的最佳方法是什么?

You could use orElse(null) : 你可以使用orElse(null)

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

You can use ifPresent and map methods instead, if the function is void and you need to do side-effects you can use ifPresent , 您可以使用ifPresentmap方法,如果函数无效并且您需要执行副作用,则可以使用ifPresent

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

If another method return relies on the Optional than that method might need to return an Optional as well and use the map method 如果另一个方法返回依赖于Optional,那么该方法可能还需要返回一个Optional并使用map方法

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

Most of the time when you call isPresent and get , you are misusing Optional . 大多数情况下,当你打电话给isPresentget ,你会误用Optional

The ifPresent that you're using doesn't require you to create a new lambda, you can just use a method reference: 您正在使用的ifPresent不需要您创建新的lambda,您只需使用方法引用:

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

This doesn't really solve the case where you want to conditionalize on the presence of two optionals, though. 但是,这并不能解决您希望以两个选项的存在为条件的情况。 But as an alternative to 但作为替代

 // And want to return if it's empty if (!o.isPresent()) return; 

why not just reverse the condition, which works nicely in the nested case, too? 为什么不只是反转条件,这也适用于嵌套的情况呢? There's no need to make the return explicit: 没有必要明确返回:

if (o.isPresent()) {
  System.out.println(o.get());
  if (oo.isPresent()) {
    System.out.println(oo.get());
  }
}

However, this kind of use case suggests that you're not really benefiting from Optional as opposed to a nullable value. 但是,这种用例表明,你并没有真正受益于Optional而不是可以为空的值。 In general, if you're using isPresent and get, then Optional might not really be getting you all that much (except that it forces you to consider the case where the value is missing). 一般来说,如果你正在使用isPresent和get,那么Optional可能并没有真正让你得到那么多(除了它会强迫你考虑缺少值的情况)。 Using ifPresent, map, filter, and other "more functional" methods might be more typical uses for an Optional value. 使用ifPresent,map,filter和其他“更多功能”方法可能是Optional值的更典型用法。


But in any case, please don't return null when you're promising an Optional. 但无论如何,当你承诺选择时,请不要返回null。 Though it's perfectly legal to return null when an object is expect, the point of Optional is precisely to avoid having to check for null. 虽然在期望对象时返回null是完全合法的,但Optional的要点正是为了避免必须检查null。 So don't do: 所以不要这样做:

 Optional<String> getOptional() { return null; } 

but instead do: 而是做:

Optional<String> getOptional() { 
  return Optional.empty();
}

Otherwise you end up having to do: 否则你最终不得不做:

Optional<String> o = getOptional();
if (o != null && o.isPresent()) {
  // ...
}

which is really just doing the same kind of thing twice. 这真的只是两次做同样的事情。 Use an Optional, or use a nullable value, but don't do both! 使用Optional,或使用可空值,但不要同时执行这两项操作!

That's a great topic, we all love functional style of programming! 这是一个很棒的话题,我们都喜欢编程的功能风格!

Often when start an implementation of a method you are given an optional right at the top. 通常在启动方法的实现时,您会在顶部获得可选权限。 At this point you start wondering, what is the best you can do to handle an empty optional, it only makes sense to exit and stop processing if that's the case. 此时你开始想知道,处理空可选项的最佳方法是什么,只有在这种情况下退出并停止处理才有意义。

STEP 1 - Explore and anylyze 第1步 - 探索和分析

public void processMedia(String mediaClassName, String mediaName) {

    // THAT MIGHT BE YOUR FIRST IDEA
    MediaClass mediaClass = mediaClassFinder.find(mediaClassName).orElse(null); 

    // RETURNING ON NULL CONDITION LIKE THE BELOW CAN BE ALRIGHT,
    // BUT POSSIBLY YOU CAN DO BETTER
    if (mediaClass == null) {
        return;
    }
    Optional<Media> media = mediaFinder.find(mediaClass.getId(), mediaName);

    // do processing

    // render the processed object
}

STEP 2 The best approach might be to extract various pieces of the implementation to a separate methods and chain them together in a functional style. 第2步最好的方法可能是将各个实现部分提取到一个单独的方法中,并以功能方式将它们链接在一起。 As a side effect of this exercise you will probably end up with much improved interface and structure of your application. 作为本练习的副作用,您可能最终会改进应用程序的界面和结构。 That's how refactoring works. 这就是重构的工作原理。 Look below, there is no explicit null assignments and no extra return points anywhere. 看下面,没有明确的空分配,也没有额外的返回点。 And the coding becomes fun. 编码变得有趣。

public void processMedia(String mediaClassName, String mediaName) {
    mediaClassFinder.find(mediaClassName)
        .flatMap(mediaClass -> mediaFinder.find(mediaClass.getId(), mediaName))
        .map(this::compress)
        .ifPresent(this::render);
}
private Media compress(Media media) {
    // compress media implementation
    return media;
}
private void render(Media media) {
    // render media implementation
}

I hope you liked my example :) 我希望你喜欢我的例子:)

I don't think what you're asking is actually possible, but I would like to suggest just taking all of your code that works directly on your String and wrap it in a function. 我不认为你提出的问题实际上是可行的,但我想建议只需将你的所有代码直接用在你的String上并将其包装在一个函数中。 So your function becomes something like this: 所以你的功能变成这样:

void m4() {
    Optional<String> o = getOptional();
    if (!o.isPresent()) return;

    doThings(o.get());
}

void doThings(String s){
    System.out.println(s);
    //do whatever else with the string.
}

This way you only have the String in scope and you don't have to call .get() everytime you want to access it. 这样,您只能在范围内使用String,并且每次要访问它时都不必调用.get()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 选修的<integer>空时从 Optional.ifPresentOrElse() 返回一个字符串?</integer> - Optional<Integer> return a string from Optional.ifPresentOrElse() when empty? 如果存在,如何返回一个对象,否则返回可选的空 - How to return an object if present otherwise return optional empty 可选的 <List<T> &gt;对于存储库层中的空列表,返回Optional.empty。 如何更改它以返回Optional [[]] - Optional<List<T>> for Empty List in Repository Layer Returns Optional.empty . How do I change it to return Optional[[]] 如何让`Map::get` 返回找到值的`Optional` 或`Optional.empty()` - How to make `Map::get` return either an `Optional` of the found value or `Optional.empty()` 使用Optional时如何在Empty的情况下设置默认值 - How to set a default Value in case of Empty when using Optional 当Optional不为空时,如何防止传递给Optional的orElse的函数被执行? - How to prevent the function passed to Optional's orElse from being executed when the Optional is not empty? 如何创建一个包含可选的哈希图,并在检索它时给我值或 Optional.empty 但有限制 - How to create a hashmap that contains optional and when retreiving it gives me the value or Optional.empty but there are restrictions 如果底层对象为空,则内置方法返回可选 - Built in method to return optional if underlying object is empty 空的“可选”类型的返回值应该是什么? - What should be the return value for empty `Optional` type? Jackson JsonNode 和 Java Streams 返回 Optional Empty - Jackson JsonNode and Java Streams to return Optional Empty
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM