Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return when an optional is empty?

I love that optionals are in the Java standard library now. But there is one basic problem that I keep running into that I haven't figured out how to solve in the best way (easiest to read and understand, prettiest, shortest):

How to return from a method when an optional is empty?

I am looking for a general solution that 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?

Or if it's not possible to get all that, what is the best way to handle this situation?

like image 227
Lii Avatar asked Jun 27 '16 20:06

Lii


People also ask

What does get () on Optional empty return?

Return value: This method returns an empty instance of this Optional class.

What if Optional is null?

If the argument supplied to Optional. of() is null, then it will throw a NullPointerException immediately and the Optional object won't be created.

Can Optional map return null?

The class invariant is that an Optional can never hold a null value, so either the map should fail or it should return an empty Optional .


2 Answers

You could use orElse(null):

String o = getOptional().orElse(null); if (o == null) {     return; } 
like image 164
dnault Avatar answered Oct 18 '22 16:10

dnault


You can use ifPresent and map methods instead, if the function is void and you need to do side-effects you can use 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<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.

like image 40
Sleiman Jneidi Avatar answered Oct 18 '22 17:10

Sleiman Jneidi