简体   繁体   中英

NULL safe object checking in JAVA 8

So i want to do a null safe check on a value contained within a value.

So I have 3 objects contained within each other:

Person has a clothes object which has a country object which has a capital

So a person may not have clothes so a check like this throws a null pointer:

if (person.getClothes.getCountry.getCapital)

How would I make a statement like this just return false if any of the objects on the path are null?

I also don't want to do it this way. (A one-liner in Java-8 if possible.

if (person !=null) {
    if (person.getClothes != null) {
        if (person.getClothes.getCountry !=null) {
            etc....
        }
    }
}

You can chain all of those calls via Optional::map . I sort of find this easier to read than if/else , but it might be just me

Optional.ofNullable(person.getClothes())
        .map(Clothes::getCountry)
        .map(Country::getCapital)
        .ifPresent(...)

These "cascade" null-checks are really paranoid and defensive programming. I'd start with a question, isn't better to make it fail fast or validate the input right before it's store into such a data structure?

Now to the question. As you have used nested the null-check, you can do the similar with Optional<T> and a method Optional::map which allows you to get a better control:

Optional.ofNullable(person.getClothes())
        .map(clothes -> clothes.getCountry())
        .map(country -> country.getCapital())
        .orElse(..)                               // or throw an exception.. or use ifPresent(...)

As you mentioned Java -8 Here is what you would like

Objects.isNull(person) //returns true if the object is null

Objects.nonNull(person) //returns true if object is not-null

Optional.ofNullable(person.getClothes())
    .flatMap(Clothes::getCountry)
    .flatMap(Country::getCapital)
    .ifPresent(...)

By using Optional, and never working with null, you could avoid null checks altogether. Since they aren't needed, you also avoid omitting a null check leading to NPEs. Still, make sure that values returned from legacy code (Map, ...), which can be null, are wrapped asap in Optional. check here

if(Objects.nonNull(person) && Objects.nonNull(person.getClothes) &&  Objects.nonNull(person.getClothes.getCountry )){
   // do what ever u want
 }

And if you are operating with Collections and using org.apache.commons then CollectionUtils.isNotEmpty(persons) and CollectionUtils.isEmpty(persons) will works for you. Where Persons is List of person.

You can achieve using single line of code

if (person != null && person.getClothes != null && person.getClothes.getCountry != null) { }

As you know there is substantial difference between = and == .

The operators && and || are short-circuiting, meaning they will not evaluate their right-hand expression if the value of the left-hand expression is enough to determine the result

If your first expression is true then only it will check for next expression.

If first expression is false then it will not check for next expression.

So as your requirement if person is not null then only check for person.getClothes != null and so on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM