Programming BS: Null
Programming BS: Null
It's not called the billion-dollar mistake for nothing! Let's see why null is terrible, the problems with Java's attempts to counter it, and some recommended practices.
Join the DZone community and get the full member experience.Join For Free
I used to watch a TV show called "Penn & Teller Bullsh**!", where a couple of entertainers named Penn and Teller would discuss various issues. At the outset of each episode, Penn would briefly introduce the topic and then point his finger at the screen and say "<topic> is bullshit!", with extra emphasis on the last word.
Ever read the article about how NULL is the billion-dollar mistake? I understand the sentiment of null's inventor, and I both agree and disagree. I disagree because the problem isn't null itself, but rather the way we have supported it in languages — and due to that support, I agree we are better off without it.
NULL is Bullshit!
Optional simply doesn't work very well. Should you use Optional for a field? Some say yes, some no. Those who say yes probably point out that by making a field Optional, all accesses to it in the class cannot ignore the potential nullness.
If a getter returns Optional, should the setter accept Optional? If the setter accepts Optional, then the caller has to incessantly wrap every value being passed, which creates extra code for every single call. If the setter simply accepts the wrapped value directly, then the wrapper only has to be dealt with one time inside the class, but breaks the expected symmetry of the getter and setter types.
Frameworks that want to scan your bean class to get type information would have to consider an Optional<T> to really be type T, since the point of Optional is simply to enforce null handling, not to change the type. This, in turn, creates a whole new slew of rules for bean processing, and each framework will likely do it slightly differently. Think of using Optional with Spring, JPA, JAXB, JSON, etc - the support is not the same across the board.
None of the JSE/JEE APIs that returned null were modified for Java 8 to use Optional. Frameworks have been slow to adopt. Spring Data 2.0 added Optional support in repository interfaces at the end of 2017, almost three and a half years after Java 8 was first released.
The best strategy is to simply avoid using null as much as possible:
- Use Objects.requireNonNull(parameter, "parameterName") in constructors and methods for every Object parameter.
- Constructors only allow the user to not specify an Object field value if that field can be initialized to a sensible default (empty String/Collection/Map, 0 for BigInteger, etc).
- Use wrappers for Collections and Maps that throw NPEs when an attempt is made add a null value, map a null key, or map a key to a null value.
- If you cannot reasonably avoid null in an internal object for some reason, then don't expose the object directly — provide an API instead that always translates nulls into something else.
- An Optional is really just a collection of at most one element. Collections.emptyList, emptySet, emptyMap, singleton, singleList, and singletonMap can be used for the same purpose, and are fully compatible with all frameworks.
This reduces the usage of null to unavoidable situations, namely those APIs that still return null.
While Optional may seem reasonable given Java's original design decisions and history, I don't believe it is in the best interest of the community. We would be better served with the replacement of null with something else, such as an Object.isEmpty() method which can be overridden with whatever logic makes sense for each class on a case by case basis, and sensible implementations for all the JSE/JEE classes. This would be no more of a burden than hashCode and equals.
Unless and until something is done in the Java language to replace null, we're better off in the meantime to simply avoid it as much as possible, to make our code more maintainable, more likely to be correct, and easier to reason about.
Opinions expressed by DZone contributors are their own.