我正在考虑从今天的代码中删除不必要的null
条件检查,主要涉及深层嵌套对象。
例如:
我有一个班级Big
,它有Small
对象及其getter和setter的引用,同样Small
引用了
Tiny
对象及其getter和setter以及Tiny
对象具有tinyLength
变量,该变量是Integer
变量。
因此,例如,如果我正在编写一个接受Big
对象参数并在最后返回tinyLength
的方法,我通常会做一些事情
像这样:
public Integer getTinyLength (Big big) {
if (big!=null && big.getSmall()!=null && big.getSmall().getTiny()!=null &&
big.getSmall().getTiny().getTinyLength()!=null) {
return big.getSmall().getTiny().getTinyLength();
}
else {
// throw exception or return null or do whatever
}
所以我的问题不是做这一切,而是为什么我不做这样的事情:
try {
return big.getSmall().getTiny().getTinyLength();
}
catch (Exception e){
//null pointer exception being a subclass of Exception class
log your error here
throw new NullPointerException();
}
我觉得第二个代码片段非常简洁而且非常简洁。做这样的事情有什么不利之处吗? 特别是当有多个嵌套对象,并且解除引用它们时,它们通常会导致高度不可读的代码/如果您错过了其中一个,也会出错,并且会导致无效。
答案 0 :(得分:1)
第一个代码示例效率低下,并且线程不安全。 getSmall()
被调用四次,getTiny()
被调用三次,getTinyLength()
被调用两次。
第二个代码示例很危险。当您想要捕获Exception
时捕获NullPointerException
可能会导致捕获您并不意味着捕获的异常。另外,构建NullPointerException
对象,抛出它,捕获它,丢弃它以及创建另一个NullPointerObject
的开销是非常重要的。
更好的是:
Integer length = null;
if (big != null) {
Small small = big.getSmall();
if (small != null) {
Tiny tiny = small.getTiny();
if (tiny != null) {
length = tiny.getTinyLength();
}
}
}
if (length != null) {
return length;
} else {
// Throw exception, return null, or do whatever
}
最好还是将代码隐藏在Big#getTinyLength()
内的getter中。
应该仔细查看您的数据模型。你有一个没有Big
的{{1}}吗?你有一个Small
不能包含Small
吗?为什么Tiny
没有长度?如果这些成员不应该<{1}},那么让JVM检查它并抛出异常,但是不要抓住它,只是为了重新抛出一个等价物之一:
Tiny
修改
如果您使用的是Java 8,那么Optional类型可以简化您的代码:
null
这从return big.getSmall().getTiny().getTinyLength();
构造public Integer getTinyLength (Big big) {
return Optional.ofNullable(big)
.map(Big::getSmall)
.map(Small:getTiny)
.map(Tiny::getTinyLength)
.orElse(null);
}
,并继续打开它以获得微小的长度值。如果Optional<Big>
为big
,或者.map(...)
调用中使用的任何映射函数返回big
,则会生成空的可选项。最后,如果存在,则返回null
的值,否则返回null
。