Null check vs Optional is present check

后端 未结 1 1804
死守一世寂寞
死守一世寂寞 2020-12-17 08:46

Can someone explain how Optional helps us avoid NullPointerException?

Optional op = someFunc()
if(op.isPresent()) {
          


        
1条回答
  •  悲&欢浪女
    2020-12-17 09:29

    Let's say you want to get a string returned by a function, convert it to upper case, and then print it out. If you have:

    String someFunc() { ... }
    

    You might be tempted to write:

    System.out.println(someFunc().toUpperCase());
    

    Of course, this throws NullPointerException if someFunc returns null. Instead, suppose we have this:

    Optional someFunc() { ... }
    

    Then

    System.out.println(someFunc().toUpperCase());
    

    won't work, since Optional doesn't have a toUpperCase method. At this point -- hopefully -- you'll be confronted with an Optional, which should make you think about the case of the Optional being empty. This helps avoid NPEs, but probably only somewhat.

    Now you might be focusing on how to get the value out of the Optional, and you might forget about the empty case. Ah, there's a get method:

    System.out.println(someFunc().get().toUpperCase());
    

    This brings back the same problem as NPE, except that the exception is NoSuchElementException instead. So if you blindly call get on an Optional, it really is pretty much the same thing as calling a method on a reference without checking whether it's null.

    (For this reason, Brian Goetz considers Optional.get to be the biggest mistake in Java 8. See his interview with Angelika Langer JAX 2015 Fragen und Antworten zu Java 8 at about 16 minutes in. I'm not sure it's the biggest, but it is a mistake. People just don't expect get to throw an exception.)

    If you're diligent about checking for null references or empty optionals, then

    Optional os = someFunc();
    if (os.isPresent()) {
        System.out.println(os.get().toUpperCase());
    }
    

    is hardly any better than the old

    String s = someFunc();
    if (s != null) {
        System.out.println(s.toUpperCase());
    }
    

    The real advantage of Optional is that it's a library class that has a fairly rich API for dealing with the empty case in a safe way. It's often possible to process the value that might be contained within an Optional by chaining a couple method calls to the method that returned the Optional in the first place. For example, we could rewrite the sample above as follows:

    someFunc().map(String::toUpperCase)
              .ifPresent(System.out::println);
    

    0 讨论(0)
提交回复
热议问题