Is there a better way to handle null exceptions for deeply nested data?

Viewed 113

I wonder whether there is a better way of handling nulls for deeply nested data?
Lets say i have 4 classes namely University, Branch, Student, Information nested one around other.

class University{
Branch branch;
//getters & setters
}
class Branch{
Student student;
//getters & setters
}
class Student{
Information information;
//getters & setters
}
class Information{
String name;
List<Boolean> attendance;
//getters & setters
}

For some reason, i want student Name to be consumed, for which we just navigate
university.getBranch().getStudent().getInformation().getName() which is prone to raise null exceptions.
For that reason we always put an if block around it to check nulls,Something like this
if(university != null && university.getBranch() != null ..... )
Above the nested depth is 4, sometimes i have depth more than 8 or 9. In those situations, something like above doesn't make sense, we are rather sacrificing clean code. I need a better approach for this problem

Below are few ways i found helpful with their own limitations:

  1. PropertySource.getNestedProperty() - Apache common beanUtils library, which almost worked for me except it throws NestedNullException which needs to be handled using try{}catch(){} which for some reason, we don't want to do. Even have issues when dealing with lists.
  2. Optionals - Java 8 provides final Class Optional
*Traditional Way :*
if (university != null) {
    Branch branch = user.getBranch();
    if (branch != null) {
        Student student = branch.getStudent();
        if (student != null) {
            Information info = student.getInformation();
            if (info != null) {
                name = info.getName();
            }
        }
    }
}

*Java 8 Optionals :*
Optional<String> optional = Optional.ofNullable(user)
  .flatMap(University::getBranch)
  .flatMap(Branch::getStudent)
  .map(Student::getInformation)
  .orElse("default");


Code looks much clean now except we need to create an object for every Optional(if we want to use that optional more than once)

  1. The Third way of doing is JSONfying entire object using Object Mapper and get that data directly
responseEntityJson = objectMapper.writeValueAsString(responseEntity);
        rootNode = objectMapper.readTree(responseEntityJson);
        DataValue = rootNode.findValue("Data");

I'm looking forward to know your opinions.

1 Answers

IMHO, it is best to avoid the possibility of null values for as many kinds of objects as possible.

For example, if your university has a list/set of students, getStudents() should never return null. It may return an empty collection, though. If the University class makes sure that getStudents() never return null, you can skip the null checks for getStudents() wherever you call it.

Also, for many other values that can be received by getters, they should logically never be null, so just let the object make sure it never returns null. If the field is immutable, you can check in the constructor for null values and later be sure that you never receive null.

If something can really be absent, Optional is a good alternative.

Related