15

Many times I find myself null checking when fetching a value from some data hierarchy to avoid NullPointerExceptions, which I find to be prone to errors and a needs a lot of boilerplate.

I've written a very simple routine which allows me to skip null checking when fetching an object...

public final class NoNPE {

    public static <T> T get(NoNPEInterface<T> in) {
        try {
            return in.get();
        } catch (NullPointerException e) {
            return null;
        }
    }

    public interface NoNPEInterface<T> {
        T get();
    }
}

I use it a bit like this...

Room room = NoNPE.get(() -> country.getTown().getHouses().get(0).getLivingRoom());

The above resulting in me getting a Room object or a null, without having to null check all parent levels.

What do you think of the above? Am I creating a problematic pattern? Is there a better way to do this in your opinion?

  • 1
    As you're apparently using Java 8, may I suggest you consider redesigning your application to use java.util.Optional instead of nulls to represent missing data? This provides handy utilities both for the case you describe and cases where you would want to carry on with default data rather than just returning a failure condition at the end of the chain.. – Periata Breatta Jan 15 '17 at 19:15
  • I think you've essentially rediscovered the Option (or Maybe) monad :) – Andres F. Feb 3 '17 at 1:17
  • It may be possible to return Optional instead of T or null : this way you could use the orElse() method directly. 18 month later, but could help someone. – Benj Aug 2 '18 at 12:31
  • Another approaches are mentioned in this post illegalargumentexception.blogspot.com/2015/03/… , one of them is using a library named kludje which has a very interesting syntax – Benj Aug 2 '18 at 12:48
13

Your solution is very smart. The problem I see is the fact that you don't know why you got a null? Was it because the house had no rooms? Was it becuase the town had no houses? Was it because the country had no towns? Was it because there was a null in the 0 position of the collection because of an error even when there are houses in positions 1 and greater?

If you make extensibe use of the NonPE class, you will have serious debugging problems. I think it is better to know where exactly the chain is broken than to silently get a null that could be hiding a deeper error.

Also this violates the Law of Demeter: country.getTown().getHouses().get(0).getLivingRoom(). More often than not, violating some good principle makes you have to implement unorthodox solutions to solve the problem caused by violating such principle.

My recommendation is that you use it with caution and try solve the design flaw that makes you have to incur in the train wreck antipattern (so you don't have to use NonPE everywhere). Otherwise you may have bugs that will be hard to detect.

  • Great answer. Yes I won't know where I got the null in the chain. In many cases though I don't care and not having to null check means the code is more readable and less prone to boilerplate error. But yes you're right in some cases where I do need to make a different logical decision if a parent object is null, then this would cause a problem. The conventional method or the Optional class might be a safer solution there. – Eurig Jones Jan 15 '17 at 15:05
  • In general, when using the Option monad, you don't care where in the chain the absent value is. When you do care about it, you'd probably use a different type, such as Either. – Andres F. Feb 3 '17 at 1:21
  • The OP's approach is similar to C# 6's ?. and ?[] operators. One example of when you might want to use such a thing is hierarchical server-side settings. var shouldDoThing = settings?.a?.b?.c ?? defaultSetting; Who cares why any part of that was null? Maybe you couldn't fetch the settings. Maybe you decided to remove a section of the settings. In any case, you can never really count on getting the server's settings, so a default is usually a good idea, and you're unlikely to care why you couldn't get the actual setting unless it happens very often when it shouldn't. – chris Feb 3 '17 at 1:48
  • Now I'm not saying that's strictly better or worse than localizing the defaults and simply getting back the value you want through normal accesses settings.a.b.c. Then again, this is a single isolated example. – chris Feb 3 '17 at 1:53
10

The idea is fine, really good in fact. Since Java 8 the Optional types exist, a detailed explanation can be found at Java Optional type. A example with what you posted is

Optional.ofNullable(country)
    .map(Country::getTown)
    .map(Town::Houses);

And further on.

  • 1
    Yes I was aware of the Optional class, from both Java 8 and Guava and they are really useful. But you can't just fetch an object as you would normally making the code a bit harder to read and a bit less performant too. But the upside is that there are many very useful operators that the Optional class provides. – Eurig Jones Jan 15 '17 at 14:57
  • 3
    @EurigJones I don't think the code becomes less performant. Readability in the eye of the beholder, but I'd argue Optional is the more readable solution of the two, if only because -- unlike your proposal -- it's a very common idiom. It's even more concise than yours! – Andres F. Feb 3 '17 at 1:17
0

Your method works well enough for its intended purpose, although returning nulls when you get a NullPointerException sounds like bad design.

Try avoiding nulls when you can and only pass them when they represent something or have special meaning and only return them when they represent/mean something - otherwise you should throw a NullPointerException. This avoids bugs and confusion. If an Object shouldn't be null, a NullPointer should be thrown. If an object can be null then nothing will go wrong when one is passed in. Otherwise your method above works.

0

I can feel your pain, but the proposed solution is a bad idea.

  • If one of the getters throws a NPE for some other reason, you will ignore it.
  • There's a risk for that inner lambda to grow into horrible code. For example, if there's a new requirement to return a special constant when there are no houses in the town, a lazy programmer can extend the lamda, leaving everything wrapped in NoNPE.get.
  • As already mentioned, Optional.map is what you are looking for.
  • The penalty of creating a new instance of NullPointerException is often significant. It's many microseconds, especially as your call stack is getting bigger. It's hard to predict where your utility will end up being used.

As a side note, NoNPEInterface is a duplicate of java.util.function.Supplier.

In some cases you might consider using an expression evaluation utils which are present in many frameworks (for example: EL, SpEL):

evaluateProperty(country, "town.houses[0].livingRoom")
  • Ok for web page templates, but generally slow to develop (no compile time checking) and slow to run. – kevin cline Feb 3 '17 at 11:46

protected by gnat Jan 16 '17 at 4:28

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.