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

JavaClassNullTernary

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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 - Java

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 - Java

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 - Java

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 - Java

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 :)

Solution 6 - Java

Instead of using null, you could use some version of the "null object" design pattern. For example:

public class Family {
    private final PersonList people;
    public Family(PersonList people) {
        this.people = people;
    }

    public PersonList getPeople() {
        if (people == null) {
            return PersonList.NULL;
        }
        return people;
    }

    public boolean isNull() {
        return false;
    }

    public static Family NULL = new Family(PersonList.NULL) {
        @Override
        public boolean isNull() {
            return true;
        }
    };
}


import java.util.ArrayList;

public class PersonList extends ArrayList<Person> {
    @Override
    public Person get(int index) {
        Person person = null;
        try {
            person = super.get(index);
        } catch (ArrayIndexOutOfBoundsException e) {
            return Person.NULL;
        }
        if (person == null) {
            return Person.NULL;
        } else {
            return person;
        }
    }
    //... more List methods go here ...

    public boolean isNull() {
        return false;
    }
    
    public static PersonList NULL = new PersonList() {
        @Override
        public boolean isNull() {
            return true;
        }
    };
}

public class Person {
    private Address address;
    
    public Person(Address address) {
        this.address = address;
    }
    
    public Address getAddress() {
        if (address == null) {
            return Address.NULL;
        }
        return address;
    }
    public boolean isNull() {
        return false;
    }

    public static Person NULL = new Person(Address.NULL) {
        @Override
        public boolean isNull() {
            return true;
        }
    };
}

etc etc etc

Then your if statement can become:

if (!family.getPeople().get(0).getAddress().getPostalCode.isNull()) {...}

It's suboptimal since:

  • You're stuck making NULL objects for every class,
  • It's hard to make these objects generic, so you're stuck making a null-object version of each List, Map, etc that you want to use, and
  • There are potentially some funny issues with subclassing and which NULL to use.

But if you really hate your == nulls, this is a way out.

Solution 7 - Java

Although this post is almost five years old, I might have another solution to the age old question of how to handle NullPointerExceptions.

In a nutshell:

end: {
   List<People> people = family.getPeople();            if(people == null || people.isEmpty()) break end;
   People person = people.get(0);                       if(person == null) break end;
   Address address = person.getAddress();               if(address == null) break end;
   PostalCode postalCode = address.getPostalCode();     if(postalCode == null) break end;

   System.out.println("Do stuff");
}

Since there is a lot of legacy code still in use, using Java 8 and Optional isn't always an option.

Whenever there are deeply nested classes involved (JAXB, SOAP, JSON, you name it...) and Law of Demeter isn't applied, you basically have to check everything and see if there are possible NPEs lurking around.

My proposed solution strives for readibility and shouldn't be used if there aren't at least 3 or more nested classes involved (when I say nested, I don't mean Nested classes in the formal context). Since code is read more than it is written, a quick glance to the left part of the code will make its meaning more clear than using deeply nested if-else statements.

If you need the else part, you can use this pattern:

boolean prematureEnd = true;

end: {
   List<People> people = family.getPeople();            if(people == null || people.isEmpty()) break end;
   People person = people.get(0);                       if(person == null) break end;
   Address address = person.getAddress();               if(address == null) break end;
   PostalCode postalCode = address.getPostalCode();     if(postalCode == null) break end;

   System.out.println("Do stuff");
   prematureEnd = false;
}

if(prematureEnd) {
	System.out.println("The else part");
}

Certain IDEs will break this formatting, unless you instruct them not to (see this question).

Your conditionals must be inverted - you tell the code when it should break, not when it should continue.

One more thing - your code is still prone to breakage. You must use if(family.getPeople() != null && !family.getPeople().isEmpty()) as the first line in your code, otherwise an empty list will throw a NPE.

Solution 8 - Java

If you can use groovy for mapping it will clean up the syntax and codes looks cleaner. As Groovy co-exist with java you can leverage groovy for doing the mapping.

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!!!
                }
            }
        }
    }
}

instead you can do this

if(family?.people?[0]?.address?.postalCode) {
   //do something
}

or if you need to map it to other object

somobject.zip = family?.people?[0]?.address?.postalCode

Solution 9 - Java

Not such a cool idea, but how about catching the exception:

    try 
	{
	    PostalCode pc = people.get(0).getAddress().getPostalCode();
	}
	catch(NullPointerException ex)
	{
        System.out.println("Gotcha");
	}

Solution 10 - Java

If it is rare you could ignore the null checks and rely on NullPointerException. "Rare" due to possible performance problem (depends, usually will fill in stack trace which can be expensive).

Other than that 1) a specific helper method that checks for null to clean up that code or 2) Make generic approach using reflection and a string like:

checkNonNull(family, "people[0].address.postalcode")

Implementation left as an exercise.

Solution 11 - Java

I was just looking for the same thing (my context: a bunch of automatically created JAXB classes, and somehow I have these long daisy-chains of .getFoo().getBar().... Invariably, once in a while one of the calls in the middle return null, causing NPE.

Something I started fiddling with a while back is based on reflection. I'm sure we can make this prettier and more efficient (caching the reflection, for one thing, and also defining "magic" methods such as ._all to automatically iterate on all the elements of a collection, if some method in the middle returns a collection). Not pretty, but perhaps somebody could tell us if there is already something better out there:

/**
 * Using {@link java.lang.reflect.Method}, apply the given methods (in daisy-chain fashion)
 * to the array of Objects x.
 * 
 * <p>For example, imagine that you'd like to express:
 * 
 * <pre><code>
 * Fubar[] out = new Fubar[x.length];
 * for (int i=0; {@code i<x.length}; i++) {
 *   out[i] = x[i].getFoo().getBar().getFubar();
 * }
 * </code></pre>
 * 
 * Unfortunately, the correct code that checks for nulls at every level of the
 * daisy-chain becomes a bit convoluted.
 * 
 * <p>So instead, this method does it all (checks included) in one call:
 * <pre><code>
 * Fubar[] out = apply(new Fubar[0], x, "getFoo", "getBar", "getFubar");
 * </code></pre>
 * 
 * <p>The cost, of course, is that it uses Reflection, which is slower than
 * direct calls to the methods.
 * @param type the type of the expected result
 * @param x the array of Objects
 * @param methods the methods to apply
 * @return
 */
@SuppressWarnings("unchecked")
public static <T> T[] apply(T[] type, Object[] x, String...methods) {
    int n = x.length;
    try {
        for (String methodName : methods) {
            Object[] out = new Object[n];
            for (int i=0; i<n; i++) {
                Object o = x[i];
                if (o != null) {
                    Method method = o.getClass().getMethod(methodName);
                    Object sub = method.invoke(o);
                    out[i] = sub;
                }
            }
            x = out;
        }
    T[] result = (T[])Array.newInstance(type.getClass().getComponentType(), n);
    for (int i=0; i<n; i++) {
            result[i] = (T)x[i];
    }
            return result;
    } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new RuntimeException(e);
    }
}

Solution 12 - Java

and my favorite, the simple try/catch, to avoid nested null checks...

try {
    if(order.getFulfillmentGroups().get(0).getAddress().getPostalCode() != null) {
        // your code
    } 
} catch(NullPointerException|IndexOutOfBoundsException e) {}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionllappallView Question on Stackoverflow
Solution 1 - JavaRobertView Answer on Stackoverflow
Solution 2 - JavaamitView Answer on Stackoverflow
Solution 3 - JavaAmit Kumar GuptaView Answer on Stackoverflow
Solution 4 - JavaPaul TomblinView Answer on Stackoverflow
Solution 5 - JavaBrianView Answer on Stackoverflow
Solution 6 - JavacharleycView Answer on Stackoverflow
Solution 7 - JavadariooView Answer on Stackoverflow
Solution 8 - Javanitesh cView Answer on Stackoverflow
Solution 9 - JavaMByDView Answer on Stackoverflow
Solution 10 - JavaMattias Isegran BerganderView Answer on Stackoverflow
Solution 11 - JavaPierre DView Answer on Stackoverflow
Solution 12 - JavaKeith KlingemanView Answer on Stackoverflow