duke_from_java_by_reallyn00b-d2zdiy7

Java Optional, WTF?

People say Java’s Optional is broken. And man is it ever!

Let’s say you have a value object, Name, like this:

public class Name {
    
    private String first;
    private String last;
    
    public Name(String first, String last) {
        this.first = first;
        this.last = last;
    }
    
    public String getFirst() {
        return first;
    }
    
    public String getLast() {
        return last;
    }
    
    public String getFullName() {
        return first + " " + last;
    }
}

And elsewhere you have these lines of code:

Optional<Name> optionalName = Optional.of(new Name(null, null));
Optional<String> optionalFirst = optionalName.flatMap(name -> Optional.of(name.getFirst()));

Seems totally reasonable! But when you run it:

Exception in thread "main" java.lang.NullPointerException
    at java.util.Objects.requireNonNull(Objects.java:203)
    at java.util.Optional.<init>(Optional.java:96)
    at java.util.Optional.of(Optional.java:108)
    at com.scottshipp.www.OptionalWTF1.lambda$main$0(OptionalWTF1.java:14)
    at java.util.Optional.flatMap(Optional.java:241)
    at com.scottshipp.www.OptionalWTF1.main(OptionalWTF1.java:14)

This is why Java’s Optional is broken!

Uh…no it’s not

But yeah, you’re a clever, observant person. You noticed that I didn’t use ofNullable in that example. It should be Optional.ofNullable(name.getFirst()).

So that totally works…

Optional<Name> optionalName = Optional.of(new Name(null, null));
Optional<String> optionalFirst = optionalName.flatMap(name -> Optional.ofNullable(name.getFirst()));

Uh… Yes it is

…but WTF? Why? Why is there an ofNullable method separate from the of method? Fucking everything in Java is nullable! Except
primitives but you can’t pass fucking primitives to either of these methods! What is this shit? What are they smoking at Oracle?

Scala only has Option (the apply method on the Option class) and it only does what ofNullable does and returns None if you pass it null:

case class Name(first: String, last: String)
val optionalName = Option(new Name(null, null))
val optionalFirst = optionalName.flatMap(name => Option(name.first))

No NullPointerException! The optionalFirst variable now holds a None.

I tried hard to fuck up Scala code as bad as Java and I could not get a NullPointerException out of it.

The worst part

Do you want to know the worst part of this? The part that makes me want to punch “Duke”, Java’s mascot, in the mouth?

The worst part is that NullPointerException is a runtime error!

And, clearly, this is something that the compiler could figure out. It turns out, that this NullPointerException is entirely on purpose, it’s part of the method contract for of (see its Javadoc). For what inhuman reasoning I can’t even guess.

The worst worst part

So now because of that, you can write a one-line Java program that compiles just fine but throws a NullPointerException:

public class OptionalWTF0 { public static void main(String[] args) { Optional.of(null); } }
Exception in thread "main" java.lang.NullPointerException
    at java.util.Objects.requireNonNull(Objects.java:203)
    at java.util.Optional.<init>(Optional.java:96)
    at java.util.Optional.of(Optional.java:108)
    at com.scottshipp.www.OptionalWTF0.main(OptionalWTF0.java:8)

Leave a Reply

Your email address will not be published. Required fields are marked *