Multiple null Checks or try/catch NullPointerException There is A LOT of information online stating that you should NEVER catch a NullPointerException.  Generally I agree, but I am wondering about this one case.

I have inherited code that requires me to access data that I need in the following way

context.getGrandParent().getParent().getChild().isRequired()


There is no guarantee that any of the objects in this hierarchy will not be null. 
 I have to enter a block if isRequired() returns true.  First, and what I initially wrote, with null checks:

if(context != null
   &amp;&amp; context.getGrandParent() != null
   &amp;&amp; context.getGrandParent().getParent() != null
   &amp;&amp; context.getGrandParent().getParent().getChild() != null 
   &amp;&amp; context.getGrandParent().getParent().getChild().isRequired()
){
   // continue with business logic
} else {
   LOG.error("Unable to determine if processing is required.");
}    
// continue with other inherited code


Setting aside that I could refactor this, perhaps for readability, wouldn't it make more sense to do the following?

boolean isRequired = false;
try {
   isRequired = context.getGrandParent().getParent().getChild().isRequired();
} catch (NullPointerException npe) {
   LOG.error("Unable to determine if processing is required.");
}

if(isRequired){
   // continue with business logic
}
// continue with other inherited code
The problem with catching NullPointerException is “which one did you catch?”  A null can be returned from getGrandParent(), and using that return value without checking will cause the exception.  OR a bug in getGrandParent() might cause an exception while trying to find the parent’s parent, and you are obscuring the bug by assuming the NullPointerException results from a properly returned null value.

You can use Optional to properly capture the null and not call subsequent function. 

Optional&lt;Boolean&gt; isRequired = Optional.ofNullable(context)
                          .map(Context::getGrandParent)
                          .map(GrandParent::getParent)
                          .map(Parent::getChild)
                          .map(Child::isRequired);

if (!isRequired.isPresent()) {
    LOG.error("Unable to determine if processing is required.");
} else if (isRequired.get()) {
    // continue with business logic
}


The Context::, GrandParent::, Parent::, Child:: class types are, of course, WAG's.  You'll need to supply the corrent types based on the type returned by the previous stage.

Alternately, you could use .getOrElse(Boolean.FALSE) at the end of the .map() chain.