Есть ли лучший способ обрабатывать нулевые исключения для глубоко вложенных данных? - PullRequest
2 голосов
/ 04 августа 2020

Интересно, есть ли лучший способ обработки нулей для глубоко вложенных данных? Допустим, у меня 4 класса, а именно: Университет , Филиал , Студент , Информация , вложенные друг в друга.

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
}

По какой-то причине я хочу, чтобы имя студента использовалось, для чего мы просто перемещаемся university.getBranch().getStudent().getInformation().getName(), который может вызывать нулевые исключения. По этой причине мы всегда помещаем вокруг него блок if, чтобы проверить нули, что-то вроде этого if(university != null && university.getBranch() != null ..... ) Выше вложенной глубины 4, иногда у меня глубина больше 8 или 9. В таких ситуациях что-то подобное выше не имеет смысла, мы скорее жертвуем чистым кодом. Мне нужен лучший подход к этой проблеме Ниже приведены несколько способов, которые я нашел полезными с их собственными ограничениями:

  1. PropertySource .getNestedProperty () - Apache common beanUtils библиотека, которая почти работала для me, за исключением того, что он выдает NestedNullException, который нужно обрабатывать с помощью try{}catch(){}, что по какой-то причине мы не хотим делать. Даже есть проблемы при работе со списками.
  2. Опции - Java 8 предоставляет 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");


Код теперь выглядит очень чистым, за исключением того, что нам нужно для создания объекта для каждого необязательного (если мы хотим использовать этот необязательный параметр более одного раза)

Третий способ сделать это: JSONfying весь объект с помощью Object Mapper и получить эти данные напрямую
responseEntityJson = objectMapper.writeValueAsString(responseEntity);
        rootNode = objectMapper.readTree(responseEntityJson);
        DataValue = rootNode.findValue("Data");

Я с нетерпением жду вашего мнения.

1 Ответ

2 голосов
/ 04 августа 2020

IMHO, лучше избегать возможности нулевых значений для как можно большего количества типов объектов.

Например, если в вашем университете есть список / набор студентов, getStudents() никогда не должен возвращать null. Однако он может вернуть пустую коллекцию. Если класс University гарантирует, что getStudents() никогда не возвращает null, вы можете пропустить нулевые проверки для getStudents(), где бы вы его ни вызывали.

Кроме того, для многих других значений, которые могут быть получены геттеры, они логически никогда не должны быть нулевыми, поэтому просто позвольте объекту убедиться, что он никогда не возвращает null. Если поле является неизменяемым, вы можете проверить конструктор на наличие нулевых значений и позже убедиться, что вы никогда не получите null.

Если что-то действительно может отсутствовать, Optional - хорошая альтернатива.

...