Java: avoid checking for null in nested classes (Deep Null checking)
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 :)
llappall
Updated on July 09, 2022Comments
-
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 about 12 yearsyou've got some accessive
}
there (forgot to remove them when refactored) -
Paul Tomblin about 12 yearsReflection isn't exactly cheap either.
-
Mattias Isegran Bergander about 12 yearsYes 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 over 6 yearsThis solution relies on catching the NPE which will perform very poorly.
-
sandpat about 5 yearsIt requires API 24 and above :(
-
Dragos Geornoiu about 4 yearsI 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 about 4 yearsThis will never be a suggested approach!!
-
Anirudh about 4 yearsIf you see .map implementation, it uses Objects.requireNonNull(mapper); and this method throws nullpointerexception if the mapper goes null.
-
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 almost 3 yearsI 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 over 2 yearsThis should be the accepted answer..