As the title says, I am wondering what the best practice is regarding the throwing of NullPointerExceptions. Specifically, if I have an external library function that can return
Regarding the original code:
synthesizer = Central.createSynthesizer(generalDesc);
if (synthesizer == null) {
// (1) throw NPE explicitly
throw new NullPointerException("No general domain synthesizer found.");
}
// (2) let the JVM throw the NPE when dereferencing
synthesizer.allocate();
My take is that throwing the NPE as shown here is OK, but with tremendous caveats. The caveat under which this is OK is only if the NPE ctor argument is a sufficiently descriptive (and hopefully unique) message (one hopefully pulled out of a constant or resource set.) Another caveat is that your main priority to get things out of the door, and such casea, this would count as an acceptable quick-n-dirty solution.
Under ideal circumstances, my preference is use exceptions specific to invalid configurations. And when those are not available, to either use NPE subclasses (like Apache Commons Math's NullArgumentException) or the old exceptions found in Apache Common Lang 2.x. That is my position for NPEs and IllegalArgument-type exceptions. I don't necessarily agree with Apache Common Lang's position on preferring to use the standard JDK exceptions over more semantically-relevant exceptions. But that's just me, and I'm getting off the tangent...
... so back to the original question. As I said before, throwing the NPE like that is ok in a quick-n-dirty way (when you are in one of those "need to get that sh1t out!!(10+1)" kind of situations.
Notice, however, this is a NPE caused by an application or systems configuration problem, as you correctly identified it. That is, the NPE is not the root cause, by a symptom or effect of another error condition (in this case, a configuration or environment error.)
Central.createSynthesizer returns null if it cannot find a suitable synthesizer, which is most often caused by a missing speech.properties file. So it's a matter of wrong setup of the system, and pretty unrecoverable from at runtime, rather than circumstances that need to be handled programmatically.
Unrecoverability is not a certainty. An application could have other ways to handle this situation programmatically.
As such, I believe throwing a NullPointerException is a valid response, since it indicates a bug (not in the code but in the deployment of the software). But since the synthesizer object is dereferenced in the very next statement, should I just let the JVM throw the NPE for me and save the null check?
I wouldn't do that, even under get-that-sh1t-out-of-the-door circumstances. The NPE thrown that way by the JVM will have a very uninformative message in it. In general, check everything for NULL and throw a descriptive exception (NPE or otherwise) when you encounter one.
Don't check for NPEs if you can guarantee that whatever you are getting (parameters for example) has already been checked for NPEs already (in a design-by-contract kind of way.)
Addendum: Considering that speech.properties gets loaded when the JVM starts needs to exist on the filesystem in (normally) "user.home" or "java.home/lib", it is puzzling that createSynthesizer doesn't straight up throw an NPE (which is what I had written originally in a Freudian slip) when it fails to find it but returns null instead.
Again, that's because the response to that situation is application specific. The application might decide to go on a limping mode with partial functionality instead of crashing and burning to the ground. If createSynthesizer
were to throw a NPE, then the API designer forces the application designer to adopt the later behavior, or go to somewhat greater lengths to implement a "limping" mode of operations (by having to use a catch/try instead of a simple if-null test.
I think that throwing a NullPointerException is the right thing to do here, because it indicates an actual bug in the deployment of the software.
Again, only if the NPE is a quick-n-dirty solution to get things out of the door. Under those conditions, it is ok. A better approach is to identify what this is, a configuration error.
So it would be better to have application specific exceptions like IllegalConfigurationException or InvalidConfigurationException or IncompleteConfigurationException. I don't like using java.lang.IllegalStateException
for such cases, because this is not caused by calling something in an invalid state. The invalid state got reached because of an invalid configuration. Maybe I'm playing semantic games, but there is something icky about using IllegalStateException in such cases (that's just me being subjective, I know.)