Exceptions have a type (e.g. "NullPointerException") and a message (e.g. "Argument cannot be null") and perhaps most usefully of all a stack trace (the line number and class name that the exception was throwthrown from and the calling line numbers and class names). If you are going to add error handling logic for random programming errors then I recommend that you capture all 3 pieces of information as otherwise you are making the process of finding and fixing the error harder than it needs to be.
See the Common Exception Methods that are available.
It is often be better to not add logic that tries to handle programming errors. For example, in a Visualforce controller class the default error handling works well and the stack trace detail can be obtained by turning on "Development Mode" for a User and reproducing the error using that User.
Running this using "Execute Anonymous":
try {
Date.valueOf((String) null);
} catch (Exception e) {
System.debug('>>> ' + e.getMessage());
}
confirms that the error message string will only contain "Argument cannot be null" (though FYI the exception thrown is of type "NullPointerException").