利用try catch块而不是重复的空值检查

时间:2016-09-28 16:56:45

标签: java null dereference object-oriented-analysis

我正在考虑从今天的代码中删除不必要的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();
}

我觉得第二个代码片段非常简洁而且非常简洁。做这样的事情有什么不利之处吗? 特别是当有多个嵌套对象,并且解除引用它们时,它们通常会导致高度不可读的代码/如果您错过了其中一个,也会出错,并且会导致无效。

1 个答案:

答案 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