If you dont trust FindBug, it may be an option to use an assertion. This way you avoid the problems mentioned by User MSalters but still have a check. Of course, this approach may not be applicable if such a fail-fast approach is not feasible, i.e. you have to catch any exception.
And to further answer the question whether it is bad practice. Well, this is arguable but I would not think so. I consider this FindBug annotation as a light specification following the design by contract principle.
In design by contract you establish a contract between a method and its caller. The contract consists of preconditions that the caller agrees to fulfill when calling the method and a postcondition that in turn is fulfilled by the method after execution if its precondition is fulfilled.
One of the benefits of this development method is that you can avoid a so called defensive programming style (in which you check for all invalid parameter values explicitly etc.). Instead you can rely on the contract, and avoid redundant checks to increase performance and readibility.
Contracts can be used for runtime-assertion checking which follows the above mentioned fail-first principle in which you want your program to fail if a contract is broken, giving you a clue to identify the source of error. (A failed precondition means that the caller did something wrong, a failed postcondition indicates an implementation error of the given method)
Furthermore, contracts can be used for static analysis, which tries to draw conclusions about the source code without actually running it.
The @nonnull annotation can be seen as a precondition that is used for static analysis by the tool FindBugs. If you prefer an approach such as runtime-assertion checking, i.e. the fail first strategy, you should consider using assertion statements as built-in Java. Or maybe to adapt to a more sophisticated specification strategy using a behavioral interface specification language such as the Java Modeling Language (JML).
JML is an extension of Java in which specification is embedded in special Java Comments. An advantage of this approach is that you can use sophisticated specification, even using a development approach in which you only rely on specification rather than implementation details and use different tools that make use of the specification, such as the mentioned runtime-assertion checking tools, automated generation of unit-tests or documentation.
If you share my point of view of @nonnull being a (light) contract, it would be common practice to not add additional checks because the original idea behind this principle is to avoid defensive programming.
I believe it is primarily historical baggage.
The most prominent and oldest language with null
is C and C++. But here, null
does makes sense. Pointers are still quite numerical and low-level concept. And how someone else said, in the mindset of C and C++ programmers, having to explicitly tell that pointer can be null
doesn't make sense.
Second in line comes Java. Considering Java developers were trying to get closest to C++, so they can make transition from C++ to Java simpler, they probably didn't want to mess with such core concept of the language. Also, implementing explicit null
would require much more effort, because you have to check if non-null reference is actually set properly after initialization.
All other languages are same as Java. They usually copy the way C++ or Java does it, and considering how core concept of implicit null
of reference types is, it becomes really hard to design a language that is using explicit null
.
Best Answer
In C,
NULL
is a macro that expands either to0
or(void*)0
(or something that has a similar effect).In the first case, you can not differentiate between
NULL
and0
, because they are literally the same.In the second case, your code will cause a compile error, because you can't compare an integer variable with a pointer.