NullPointerExceptions are a pain. They arise from looking for items in collections (caches, maps, list, databases, filesystems... the list goes on) and assigning nulls to variables or accessing them.
Filesystems have a good approach to failed references -- FileNotFoundException -- Except, this gets clouded in with IOException, so it's not so visible and useful.
I've found that having these *NotFound exceptions extending from Exception are super useful and extensive use of them have eliminated most all of my NPEs.
When I search my database or lookup a key from a cache, my finders typically throw a NotFound variant and in my code, I know where I could have an empty value that would normally disrupt my code, and now I have a place where I can log it or deal with it.
try{
Record r = table.where(F_ID+"=?",id);
r.doStuff();
}catch(RecordNotFoundException e){
LOG.info("whoops - id " + id + " not found?",e);
}
For smaller things like arrays or maps, check length or existence before you check for nulls .
if(map.contains(id)){
map.get(id).doStuff();
}else{
LOG.info("whoops - id " + id + " not found?",e);
}
if(arr.length < index && arr[index] != null){
arr[index].doStuff();
}else{
LOG.info("whoops - index " + index + " not found?",e);
}
The other place they come from is from bad instantiation like "Long id = null" and then references to id as if it were not -- This is just plain bad coding, you should not initialize it if you are just going to set it to null. Usually this is done so that the developer can search/evaluate a situation, and then set the value -- But if your searches throw NotFound's and your existence checks are in if blocks, your logical elements should prevent you from accessing a null value -- Because you would have to directly assign it.
Because NPE's are typically from bad searches, and that there are ways to circumvent these failures that incorporate good coding practices, that null checks are sometimes considered bad habit.
The best way to avoid NPE's is to never allow a null to be assigned with good coding habits.
So my answer is: you check for nulls if you are working on bad code. You just have to. But if it's all your code, you should never be returning nulls or assigning them.