[JAVA] Don't use `get ()` ~ Defeated Optional

When I looked at the articles about Java Optional, I saw a lot of people saying, "This teaching method produces only those who use ** Optional, which doesn't have a clear meaning ...", so at least I read this article as a rebellion. write.

TL; DR

For those who only know ʻis Present ()andget ()`

yamero.png

Don't write this way

When looking at the article

Null check is done with ʻOptional # isPresent (), and the value is fetched with ʻOptional # get ().

There are too many explanations like.

** Don't do that **. Then ** nothing is different from the conventional null check **. Instead of staying the same, the number of types has increased, the execution time has increased, the memory usage has increased **, and only the disadvantages have been added **. I haven't got any merit.

Optional<String> someStr = Optional.of("Hello, world!");

if (someStr.isPresent()) {
    System.out.println(someStr.get()); //Don't do it
}

The first thing to keep in mind is that ** ʻOptional # get ()` should not be used **.

It's important, so I'll say it again.

** ʻDo not use Optional # get () `**. </ span>

ʻOptional # get ()` is ** a poop-like method that retrieves without worrying about whether it is null or not **. It's ** Unsafe **. It is prepared in ** only ** for "when you have to use it anyway".

<!-"It's okay because I'm checking null just before" or something like that, ** Antony Hoare will come back to this article after being fucked by a butt **. If "it's okay because I'm checking null", ** the conventional method is enough **. It's ** meaningless **. You can use ** ʻOptional # get ()` even if you forget to check ** null. ** And crash **. It's a silly story. ->

The guy who skips "I'm okay because I'm checking null just before" ** I'll come back to this article after being angry at Antony Hoare **. If "it's okay because I'm checking null", ** the conventional method is enough **. It's ** meaningless **. You can use ** ʻOptional # get ()` even if you forget to check ** null. ** And crash **. It's a silly story.

Then what should we do. ** ʻUse Optional # ifPresent () `**. This method takes a method reference as an argument. So, I'll write the lambda expression inside ... ** You don't need to know the lambda expression or the method reference, just write it like that **.

Optional<String> someStr = Optional.of("Hello, world!");

someStr.ifPresent(x -> {
    System.out.println(x);
});

ʻThe method reference passed to Optional # ifPresent () is executed only when it is not ** null **. You can think of xas a ** temporary variable **. Of course, the name is free (unless you wear it). The type is naturallyT for ʻOptional <T>. It's best to know about lambda expressions and method references, but even if you don't know it, it should be enough because it looks like a regular if statement **.

There may be cases where you don't want to execute it only when it is not null, but you want to divide the operation according to the presence or absence of ** value **.

Optional<String> someStr = Optional.empty();

if (someStr.isPresent()) {
    System.out.println(someStr.get()); //Of course don't do it
} else {
    System.out.println("There was no value");
}

In that case, use ** ʻOptional # ifPresentOrElse ()` **.

Optional<String> someStr = Optional.empty();

someStr.ifPresentOrElse(x -> {
    System.out.println(x);
}, () -> {
    System.out.println("There was no value");
});

()-> ... means a lambda expression with no arguments, but of course you can think of it as "a magic when you don't use a value".

Note that ʻOptional # ifPresentOrElse ()` was implemented in Java 9, so in a Java 8 environment

Optional<String> someStr = Optional.empty();

someStr.ifPresent(x -> {
    System.out.println(x);
}); if (!someStr.isPresent()) {
    System.out.println("There was no value");
}

There will be no choice but to.

Do not use ʻOptional # ifPresent ()` as much as possible

** If possible, ʻOptional # ifPresent () should not be abused ** either. ʻOptional # map (), ʻOptional # flatMap () and ʻOptional # orElse () should often be sufficient. In the world of Optional, it is basic ** that there is no ** null check.

For example, the example of ʻOptional # ifPresentOrElse () mentioned above can be written more concisely by using these methods. If you use ʻOptional # orElse () to unwrap by specifying a substitute value when it was ʻempty`,

Optional<String> someStr = Optional.empty();

System.out.println(someStr.orElse("There was no value"));

This is fine. What if ʻOptional instead of ʻOptional <String>? Then it's time for ʻOptional # map () to apply the function only when it's not ʻempty.

Optional<Integer> someInt = Optional.empty();

System.out.println(someInt.map(x -> x.toString()).orElse("There was no value"));

It can be written more concisely if you study method references.

Optional<Integer> someInt = Optional.empty();

System.out.println(someInt.map(Object::toString).orElse("There was no value"));

Of course, if you think that one line is long, you can define a variable outside and pull it out.

For more various examples, see this article.

There are too many losers and articles for losers are written

Since there are many self-proclaimed commentary articles that give birth to losers, ʻOptional # get ()` is not used in the first place, or the basic basic part that it is ideal not to check null itself is not well known, so it is better not to have “Optional” etc. ”, a ** tongue-in-cheek article ** will be written.

  • Replace NullPointerException with NoSuchElementException. The program still crashes.

If myOPoint does not hold the actual coordinates, myOPoint.get (). X will throw NoSuchElementException and crash the program. This is nothing better than the original code. That's because the programmer's goal is to avoid all crashes, not just the ones caused by the NullPointerException.

Again, both codes are similar, and ʻOptional` is not superior to traditional referencing methods.

soreha.jpg

Well, the author of this article probably wrote such an article because there were too many defeaters. ~~ Still, there are some descriptions that he doesn't know anything about it. ~~

An example where you might have to use ʻOptional # get () `

Due to the specifications, ** processing that can cause exceptions cannot be handled outside **.

public static int half(int even) throws Exception {
    if (even % 2 == 0); else {
        throw new Exception();
    }
    
    return even / 2;
}

/* ... */

Optional<Integer> someInt = Optional.of(16);

/*it can*/
try {
    if (someInt.isPresent()) {
        System.out.println(half(someInt.get()));
    }
} catch (Exception e) {
    System.out.println("Please pass an even number");
}

/*Can not*/
try {
    someInt.ifPresent(x -> {
        System.out.println(half(x));
    });
} catch (Exception e) {
    System.out.println("Please pass an even number");
}

In order to manage this, various hacks are introduced in Qiita. I think it can be managed by using Either. It ’s a monad. Well, Java isn't officially Either.

Recommended Posts

Don't use `get ()` ~ Defeated Optional
Don't use magic numbers ...
How to use java Optional
Item 26: Don't use raw types
[Java] How to use Optional ②
[Java] How to use Optional ①
How to use Java HttpClient (Get)