【问题标题】:Taking advantage of try catch block instead of doing repeated null checks利用 try catch 块而不是重复进行空检查
【发布时间】:2017-02-06 18:53:47
【问题描述】:

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

我觉得第二个代码 sn-p 非常简洁明了。做这样的事情有什么缺点吗? 尤其是当有多个嵌套对象时,取消对每个对象的引用通常会导致代码高度不可读/如果您错过其中一个对象并导致 null 也容易出错。

【问题讨论】:

  • 您可能会发现这很有帮助stackoverflow.com/questions/14813877/…
  • 这在 Groovy 和 Kotlin 中得到了很好的解决。我不会费心在纯 Java 中处理如此长的空检查。
  • 好吧,你当然可以去。它将使代码更具可读性。根据this 的问题,使用try-catch 博客并没有那么 昂贵。
  • 这些对象中的任何一个可能为空的可能性有多大?如果它根本不可能(甚至例外),那就是例外的目的。但是我认为,如果这些对象经常为空(按设计),那么捕获异常要比完全避免异常更昂贵。如果您的应用不是性能关键,我不会担心。
  • 我会尝试捕捉特定的异常。不要将所有内容都归为Exception - 这不是好习惯,最终会咬你。

标签: java null dereference object-oriented-analysis


【解决方案1】:

第一个代码示例效率低下,线程不安全。 getSmall() 被调用 4 次,getTiny() 被调用 3 次,getTinyLength() 被调用 2 次。

第二个代码示例很危险。当您只想捕获 NullPointerException 时捕获 Exception 可能会导致捕获您无意捕获的异常。此外,构造 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 中。

应该认真审视您的数据模型。你能有一个没有SmallBig 吗?你能有一个不包含TinySmall 吗?为什么Tiny 没有长度?如果这些成员不应该曾经是null,那么让 JVM 检查它并抛出一个异常,但不要捕获它,只是为了重新抛出一个等价的:

return big.getSmall().getTiny().getTinyLength();

编辑

如果您使用的是 Java 8,那么 Optional 类型可以简化您的代码:

public Integer getTinyLength (Big big) {
    return Optional.ofNullable(big)
        .map(Big::getSmall)
        .map(Small:getTiny)
        .map(Tiny::getTinyLength)
        .orElse(null);
}

这会从big 构造一个Optional<Big>,并继续对其展开以得到微小的长度值。如果bignull,或者如果.map(...) 调用中使用的任何映射函数返回null,则会产生一个空的可选项。最后,如果存在则返回Optional<Integer> 的值,否则返回null

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 2018-02-16
    相关资源
    最近更新 更多