Live data from Hacker News

Java 8’s new Optional type doesn't solve anything

medium.com

21–30 of 197 posts

Re: Java 8’s new Optional type doesn't solve anything

#21
post #6
post #4

Earlier quoted context omitted.

The problem is that you don't get guarantees that something is not null; you can still do Optional myOptional = null. Second, you're not required to handle the not-present case. Third, if you attempt to get the value of an optional (using .get()) when it is not present, you get an (unchecked, so no requirement to catch) exception - basically replacing NullPointerException with NoSuchElementException. The only value O…

At least one of the values of Optional is to communicate in the API that a value can be missing. The article mentions that: A programmer looking at the code for the first time will know, just by looking at the return type, "Hey, this method may not return a record! I'll have to handle that scenario." Making this clear to users of an API is something that nullable properties can not do. The user has to deliberately ig…

> A programmer looking at the code for the first time will know, just by looking at the return type, "Hey, this method may not return a record! I'll have to handle that scenario."

Well, that's basically the same thing with any nullable return then. Wether I return T or Optional, there might be no record.

Even worse, when I return T, you only have 2 cases : I return something, or I return null.

With optional, you have 3 cases to check : I returned Something, I returned Optional.of(null), or I returned null.

Re: Java 8’s new Optional type doesn't solve anything

#22

Shameless self plug "Comparing Optionals and Null in Swift, Scala, Ceylon and Kotlin" http://codemonkeyism.com/comparing-optionals-and-null-in-swi...

What is the `nice` language you refer to?

This is an old JVM language

http://nice.sourceforge.net/

I've included nice as it had a different syntax for optionals (?Type instead of Type?) which I found interesting. I was interested in Nice back in the day.

Re: Java 8’s new Optional type doesn't solve anything

#23
It's not a get out of jail free card no, but it's value isn't in preventing null pointers. The value of Optional is in providing intent.

You also get map, filter, flatMap, orElse, orElseGet, ifPresent. These are all great ways of making your code more functional, and do more with less.

I don't think annotations are the answer either, as you can't always rely on static analysis to prevent errors, a lot will still appear at runtime.

Re: Java 8’s new Optional type doesn't solve anything

#24
Adding my voice to the din of people noting how far afield of the point the author is:

You should almost never call .get(), except in cases where the code path does not allow an empty optional.

Even so, calling .get() on an empty optional is better than handing nulls around. A null may -- by chance, really -- make it several lines down the code, so that the stack trace points you much later in the code than where the null originated. Calling .get() on an empty optional immediately throws a NoSuchElementException, pointing you directly to the line where the optional was empty where it shouldn't have been.

Consider this code:

    User user = getUser();
    // other stuff here
    // ...
    // ...
    String userSummary = formatUserSummary(user);
    // ...
    // ...
where

    public String formatUserSummary(User user){
        return "Franchise Location: " + 
            user.getFranchise().getLocation().getName() + 
            " Username: " + 
            user.getUsername();   
    }
An NPE occurs inside of formatUserSummary. Where did the null come from? Is the user's Franchise null? Maybe the Franchise's Location? Or is it the User that's null?

If you instead took an Optional, even if you just immediately unwrapped it with .get(), you'd at least get an error that unambiguously told you that it was the user that was missing.

Re: Java 8’s new Optional type doesn't solve anything

#25
post #18

The author is missing the point. The fact that Optional can result in a nullpointer doesn't mean you should use in the same manner as null-checks. You shouldn't replace: if(x == null) { y = x.doSomething(); } with if(optionalX.isPresent()) { y = x.doSomething(); } You should replace it with: y = Optional.ofNullable(x) .map(ClassX::doSomething) .orElse(null);

The author is missing the point.

Is he? The point is that in Java you are still able to treat x unsafely, while languages with stronger typing do not. E.g. in Haskell, if a function returns a Maybe a, it will always be a Just a or Nothing value. Moreover, such languages allow you to make non-exhaustive matching against all constructors a compiler error.

tl;dr: Haskell, Rust, et al. put the burden on the compiler. Java puts the burden to ensure safety on the programmer. (As can be witnessed in your snippet.)

Re: Java 8’s new Optional type doesn't solve anything

#26
post #4
post #2

TL;DR You can call `Optional.get()` to deliberately circumvent the safety mechanisms of Optional. The author apparently concludes that since it does not solve ALL error cases it does not solve ANY error cases...

The problem is that you don't get guarantees that something is not null; you can still do Optional myOptional = null. Second, you're not required to handle the not-present case. Third, if you attempt to get the value of an optional (using .get()) when it is not present, you get an (unchecked, so no requirement to catch) exception - basically replacing NullPointerException with NoSuchElementException. The only value O…

I disagree with some of your points.

The fact that you can get a null instance of Optional is not Java specific - Scala has the same issue, for example. Saying that Optional does not sort any problem because there is no way to enforce it cannot be null is just wrong - it sorts plenty of problems, just not all of them (you didn't mention the case of an optional that contains null, which is unpleasant as well).

You can indeed call .get - so can you in Scala (.get) or Haskell (fromJust) with exactly the same semantics. What do you propose for the case where you know that there is a value in there but can't make the type system aware of that fact (you've called isPresent beforehand)? pattern matching and fail in the empty case? How is that different from calling get? Is it because of the fact that the exception is unchecked? In that case, why not throw a more specific, checked exception through orElseGet? And if you know that there is data to be had, isn't that exactly why we have unchecked exceptions in the first place?

You absolutely are required to handle the not-present case - you can't treat an Optional an a T, and someone will need to decide what to do at some point. Either the caller (ie you return an Optional yourself after mapping into it) or you. There's a wide range of ways you can do that, one of which being "I want to fail if there is no data" - that's either .get if you don't need a checked exception or .orElseGet if you need something more constrained. You can also decide to use a default value, or o different code path entirely...

Optional has issues - it can contain reference to a mutable variable, for exemple, or you might find yourself with a null optional or an optional that contains null. It's not perfect. It's also a lot better than the alternative, null, as it lets you communicate some of your constraints to the compiler and allow it to catch certain kinds of errors at compile-time rather than at runtime. Rather like the rest of the Java type system, in fact - it's far from perfect, it doesn't catch all type errors at compile time, but it's (arguably) better than a fully dynamic one.

Re: Java 8’s new Optional type doesn't solve anything

#27
post #18

The author is missing the point. The fact that Optional can result in a nullpointer doesn't mean you should use in the same manner as null-checks. You shouldn't replace: if(x == null) { y = x.doSomething(); } with if(optionalX.isPresent()) { y = x.doSomething(); } You should replace it with: y = Optional.ofNullable(x) .map(ClassX::doSomething) .orElse(null);

Close, but not quite there. You should leap over tall buildings to make sure that you never have to set y to null.

In my code, I'm only dealing with null if a API gives me one. At that point, I take some sort of action to make absolutely sure I'm not passing it along to anyone else. This means using exceptions, the null object pattern, or Optional without a need to dereference. The goal is to prevent a proliferation of references that could be null and therefore have to be checked.

Re: Java 8’s new Optional type doesn't solve anything

#28

Adding my voice to the din of people noting how far afield of the point the author is: You should almost never call .get(), except in cases where the code path does not allow an empty optional. Even so, calling .get() on an empty optional is better than handing nulls around. A null may -- by chance, really -- make it several lines down the code, so that the stack trace points you much later in the code than where the…

> Where did the null come from?

A bit offtopic but SAP JVM puts that info in NPE error message[1], I don't know why others implementations don't, maybe it is incurring too large overhead?

[1] it is something like "Attempted to call getLocation() on Franchise object returned from getFranchise() but it was null"

Re: Java 8’s new Optional type doesn't solve anything

#29

I don't understand what's wrong with get() method. Swift has built-in null-safety and it has "!" operator. Kotlin has it. Even Haskell has fromJust function which does exactly the same. May be name "get()" is too short and innocent-looking.

Partial functions such as fromJust are generally frowned upon in the Haskell community. There was a relatively recent proposal to deprecate and then remove fromJust:

https://mail.haskell.org/pipermail/libraries/2015-February/0...

Re: Java 8’s new Optional type doesn't solve anything

#30
post #14

Using get() is just bad style and so is returning null where you could return Collections.emptyList(). Previous discussion on reddit: https://www.reddit.com/r/programming/comments/3pl7o0/java_8s... tl;dr: use map, orElseGet, orElse

I feel get is acceptable style if you actually want to fail when there is no data to be had.

If you don't have a default value to provide, nor an alternate code path other than "sod this, I'm bailing", get is ok. Not quite as good as using a more specific exception through orElseGet, but not bad, exactly.

Also, if you have just called isPresent (and assume your data to be immutable), then get is ok - the alternative being to manually throw something like new IllegalStateException("the impossible has happened!"), which is not that much more useful, and is a pain to have to write all the time when you know it will not get called.

Post reply on HN