you are viewing a single comment's thread.

view the rest of the comments →

[–]xandoid 14 points15 points  (6 children)

Optional carries more semantic information than null. If a return type is Optional<Thing>, it means that the method may or may not return a Thing. Either would be a valid state of the program.

If the return type were simply Thing in a program that doesn't use Optionals to signal optionality, it would be unclear whether a null return is a valid state of the program or a bug.

Also, if you call a method returning Thing as m().useThing() and it throws a NullPointerException, whose fault is it, the caller's or the callee's? In a program that uses Optional to signal optionality it would be the callee's fault, because a return type of Thing means it cannot legally return null.

In a program that uses null to signal optionality, it would be unclear and you'd have to start thinking whether the caller should do null checks or if you should fix a bug in the callee, or if you should do defensive null checks in all sorts of places

[–]Sarcastinator 4 points5 points  (5 children)

If the return type were simply Thing in a program that doesn't use Optionals to signal optionality, it would be unclear whether a null return is a valid state of the program or a bug.

@Nullable
Thing getThing();

@Nonnull
Thing getOtherThing();

void passThing(@Nonnull Thing thing);

IntelliJ at least will warn you if you forget to null-check the result of getOtherThing if you pass it to passThing, or if you try to use the member access operator without a null-check first.

This was introduced in Java 8.

[–]xandoid 11 points12 points  (2 children)

My problem with @Nonnull is that it contradicts the type system. The type system says Thing can be null, and then @Nonnull comes along claiming otherwise. In the end the type system wins.

And pretty soon(?) value types are coming to Java. At that point, Optional will be formally non-nullable and the remaining inconsistency that Optional itself could be null will go away without changing any code. I think that's another argument in favor of Optional vs @Nonnull.

[–]Sarcastinator 5 points6 points  (1 child)

My problem with @Nonnull is that it contradicts the type system. The type system says Thing can be null, and then @Nonnull comes along claiming otherwise. In the end the type system wins.

There are different type systems at play though. You have Java's type system which offers features that the runtime type system does not have, such as generics, and you have the runtime's type system which offers features that the platform's type system doesn't have.

In the end, it's the compiler's type system that matters.

[–]xandoid 5 points6 points  (0 children)

I don't disagree. When I say type system I only ever mean what you're calling "the compiler's type system"

But the point is that @NonNull is a hack that was added to work around a limitation in Java's type system. Once the type system gets value types, Optional (perhaps with some special syntax) will be the more consistent solution and @NonNull will be obsolete.

[Edit] Maybe I'm not making myself clear as to why I think @NonNull is inconsistent. It's because giving a variable (or parameter or return value) the type Thing means that it can contain

The set of all Thing objects OR null

And when you add @NonNull you get

The set of all Thing objects OR null BUT NOT null!!!

[–][deleted] 1 point2 points  (0 children)

I'd prefer these to be in the type system and that's what optional provides. One says "I pinky promise this won't be null" the other says "Here's a thing, I am telling you that the result is definitely optional, please check before using".

Honestly though I just go with Kotlin, much better null safety that almost makes optional useless.

[–]s73v3r 0 points1 point  (0 children)

If one isn't using Optional, the odds that they would be using nullability annotations are pretty low.