英文:
Is there a better way to handle null exceptions for deeply nested data?
问题
我想知道是否有更好的方法来处理深度嵌套数据的空值?假设我有4个类,分别是University、Branch、Student、Information,它们相互嵌套。
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。在这些情况下,像上面那样的做法不太合理,我们更愿意牺牲清晰的代码。我需要一个更好的方法来解决这个问题。
以下是我发现有帮助的一些方法,它们各自有自己的限制:
-
PropertySource.getNestedProperty() - Apache common beanUtils库,几乎可以满足我的需求,但它会抛出
NestedNullException
,需要使用try{}catch(){}
来处理,但出于某种原因,我们不想这样做。在处理列表时也存在问题。 -
Optionals - Java 8提供了最终的Optional类
// 传统方式:
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");
现在代码看起来更干净,但如果我们要多次使用该Optional,就需要为每个Optional创建一个对象。
- 第三种方法是使用对象映射器(Object Mapper)将整个对象转换为JSON,然后直接获取数据
responseEntityJson = objectMapper.writeValueAsString(responseEntity);
rootNode = objectMapper.readTree(responseEntityJson);
DataValue = rootNode.findValue("Data");
我期待了解您的意见。
英文:
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:
- PropertySource.getNestedProperty() - Apache common beanUtils library, which almost worked for me except it throws
NestedNullException
which needs to be handled usingtry{}catch(){}
which for some reason, we don't want to do. Even have issues when dealing with lists. - 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)
- 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
得分: 2
IMHO,尽可能避免各种对象的空值可能性是最佳选择。
例如,如果您的大学有一个学生列表/集合,getStudents()
不应该返回 null
。但可以返回一个空集合。如果 University
类确保 getStudents()
不会返回 null
,则可以在调用它的任何地方省略对 getStudents()
的空值检查。
此外,对于许多其他可以通过 getter 方法接收的值,它们在逻辑上不应该为空,所以让对象确保它永远不会返回 null
。如果字段是不可变的,您可以在构造函数中检查空值,然后确保您永远不会收到 null
。
如果某些情况下确实可能不存在,Optional
是一个很好的选择。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论