Java: avoid checking for null in nested classes (Deep Null checking)

24,379

Solution 1

You can use for:

product.getLatestVersion().getProductData().getTradeItem().getInformationProviderOfTradeItem().getGln();

optional equivalent:

Optional.ofNullable(product).map(
            Product::getLatestVersion
        ).map(
            ProductVersion::getProductData
        ).map(
            ProductData::getTradeItem
        ).map(
            TradeItemType::getInformationProviderOfTradeItem
        ).map(
            PartyInRoleType::getGln
        ).orElse(null);

Solution 2

Your code behaves the same as

if(family != null &&
  family.getPeople() != null &&
  family.people.get(0) != null && 
  family.people.get(0).getAddress() != null &&
  family.people.get(0).getAddress().getPostalCode() != null) { 
       //My Code
}

Thanks to short circuiting evaluation, this is also safe, since the second condition will not be evaluated if the first is false, the 3rd won't be evaluated if the 2nd is false,.... and you will not get NPE because if it.

Solution 3

If, in case, you are using java8 then you may use;

resolve(() -> people.get(0).getAddress().getPostalCode());
    .ifPresent(System.out::println);

:
public static <T> Optional<T> resolve(Supplier<T> resolver) {
    try {
        T result = resolver.get();
        return Optional.ofNullable(result);
    }
    catch (NullPointerException e) {
        return Optional.empty();
    }
}

REF: avoid null checks

Solution 4

The closest you can get is to take advantage of the short-cut rules in conditionals:

if(family != null && family.getPeople() != null && family.people.get(0) != null  && family.people.get(0).getAddress() != null && family.people.get(0).getAddress().getPostalCode() != null) {
                    //FINALLY MADE IT TO DO SOMETHING!!!

}

By the way, catching an exception instead of testing the condition in advance is a horrible idea.

Solution 5

I personally prefer something similar to:

nullSafeLogic(() -> family.people.get(0).getAddress().getPostalCode(), x -> doSomethingWithX(x))

public static <T, U> void nullSafeLogic(Supplier<T> supplier, Function<T,U> function) {
    try {
        function.apply(supplier.get());
    } catch (NullPointerException n) {
        return null;
    }
}

or something like

nullSafeGetter(() -> family.people.get(0).getAddress().getPostalCode())

public static <T> T nullSafeGetter(Supplier<T> supplier) {
    try {
        return supplier.get();
    } catch (NullPointerException n) {
        return null;
    }
}

Best part is the static methods are reusable with any function :)

Share:
24,379
llappall
Author by

llappall

Updated on July 09, 2022

Comments

  • llappall
    llappall almost 2 years

    Imagine I have a class Family. It contains a List of Person. Each (class) Person contains a (class) Address. Each (class) Address contains a (class) PostalCode. Any "intermediate" class can be null.

    So, is there a simple way to get to PostalCode without having to check for null in every step? i.e., is there a way to avoid the following daisy chaining code? I know there's not "native" Java solution, but was hoping if anyone knows of a library or something. (checked Commons & Guava and didn't see anything)

    if(family != null) {
        if(family.getPeople() != null) {
            if(family.people.get(0) != null) {
                if(people.get(0).getAddress() != null) {
                    if(people.get(0).getAddress().getPostalCode() != null) {
                        //FINALLY MADE IT TO DO SOMETHING!!!
                    }
                }
            }
        }
    }
    

    No, can't change the structure. It's from a service I don't have control over.

    No, I can't use Groovy and it's handy "Elvis" operator.

    No, I'd prefer not to wait for Java 8 :D

    I can't believe I'm the first dev ever to get sick 'n tired of writing code like this, but I haven't been able to find a solution.

  • amit
    amit about 12 years
    you've got some accessive } there (forgot to remove them when refactored)
  • Paul Tomblin
    Paul Tomblin about 12 years
    Reflection isn't exactly cheap either.
  • Mattias Isegran Bergander
    Mattias Isegran Bergander about 12 years
    Yes indeed it can be slow as well @paul . Especially method lookup etc. Actual method invocation though can be quite fast, but again it depends (other optimizations might be harder for the VM). So cacheing the method/field lookups is usually important from my experience if it is needed. Most of all it of course depends on how often the code is used at all.
  • mojoken
    mojoken over 6 years
    This solution relies on catching the NPE which will perform very poorly.
  • sandpat
    sandpat about 5 years
    It requires API 24 and above :(
  • Dragos Geornoiu
    Dragos Geornoiu about 4 years
    I can't think of a situation where it is ok to catch a NullPointerException (maybe there are a few exceptions), it is a bad practice because generally a NPE is a programming error, a correct program should not generate one, when the programmer just catches the NPE it feels like he is trying to cover it up.
  • Anirudh
    Anirudh about 4 years
    This will never be a suggested approach!!
  • Anirudh
    Anirudh about 4 years
    If you see .map implementation, it uses Objects.requireNonNull(mapper); and this method throws nullpointerexception if the mapper goes null.
  • Andrea Polci
    Andrea Polci over 3 years
    @Anirudh the mapper, in this case, is the method reference and is never null. The value returned by the mapper can be null, and in that case the map returns Optional.empty()
  • daltonfury42
    daltonfury42 almost 3 years
    I am in favour of this. Can someone explain why it's poor? Is it because the getters might internally through an NPE due to a different bug, and it will get masked?
  • Taher
    Taher over 2 years
    This should be the accepted answer..