Hacker News new | ask | show | jobs
by jcrites 3890 days ago
No, annotations do not accomplish the same thing in practice. Annotations function properly only when the code was written with annotations, and where the code and all callers are checked against the annotations. Unfortunately, annotations miss the mark in some practical cases:

1) A reference is @NonNull in my code, and I pass it to a component that accepts a regular reference as input. The annotation semantic is simply lost, and I may not even realize it as I'm writing that code. By comparison, if I need to pass an Optional<T> reference where a T reference is needed, then the type system reminds me to consider the present and absent cases. Optional does not allow the programmer to forget.

2) The fact that a component or library was written with annotations does not mean that all usage of the library will properly check the annotations. Sometimes people forget, or sometimes they interact with a component in a dynamic way like through Spring and the semantics get lost. An Optional makes this impossible to forget. You can confuse a @Nullable T with a T, or forget to check upon conversion, but there is no failure case that causes an Optional<T> to turn into a T without handling the present and absent cases.

More choice is better than less choice. You could design an Optional type to omit the get() method. That's less useful than what we have now. Like goto, it has rare but legitimate uses, and it's easy to avoid for the "right way" in the average case (don't use it, flag it during code review, and document the reason why when it's being used).