Java 利用try-catch块而不是重复执行空检查
我正在考虑从今天的代码中删除不必要的Java 利用try-catch块而不是重复执行空检查,java,null,dereference,object-oriented-analysis,Java,Null,Dereference,Object Oriented Analysis,我正在考虑从今天的代码中删除不必要的null条件检查,这些检查主要涉及深嵌套对象。 例如: 我有一个类Big,它引用了Small对象及其getter和setter,同样Small也引用了 Tiny对象及其getter和setter和Tiny对象具有tinyleength变量,该变量是整数变量 例如,如果我正在编写一个方法,它接受一个Big对象参数,并在最后返回tinyleength,我通常会做一些事情 像这样: public Integer getTinyLength (Big big) {
null
条件检查,这些检查主要涉及深嵌套对象。
例如:
我有一个类Big
,它引用了Small
对象及其getter和setter,同样Small
也引用了
Tiny
对象及其getter和setter和Tiny
对象具有tinyleength
变量,该变量是整数
变量
例如,如果我正在编写一个方法,它接受一个Big
对象参数,并在最后返回tinyleength
,我通常会做一些事情
像这样:
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();
}
我觉得第二段代码非常简洁,切中要害。这样做有什么缺点吗?
特别是当存在多个嵌套对象时,取消对每个嵌套对象的引用通常会导致代码高度不可读/如果错过其中一个对象,则容易出错,并导致null。第一个代码示例效率低下,线程不安全
getSmall()
被调用四次,getTiny()
被调用三次,getTinyLength()
被调用两次
第二个代码示例很危险。当您只想捕获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中
应该认真研究一下您的数据模型。你能要一个大的而不是小的吗?你能要一个不含Tiny
的Small
吗?为什么Tiny
没有长度?如果这些成员不应该为null
,那么让JVM检查它并抛出异常,但不要捕获它,只是重新抛出一个等价的异常:
return big.getSmall().getTiny().getTinyLength();
编辑 如果您使用的是Java 8,那么该类型可以简化您的代码:
public Integer getTinyLength (Big big) {
return Optional.ofNullable(big)
.map(Big::getSmall)
.map(Small:getTiny)
.map(Tiny::getTinyLength)
.orElse(null);
}
这将从
big
构造一个可选的
,并继续展开它以获得微小的长度值。如果big
为null
,或者调用中使用的任何映射函数返回null
,则生成一个空的可选值。最后,如果存在可选值
,则返回该值,否则返回null
。您可能会发现这很有帮助,Groovy和Kotlin中对此进行了优雅的处理。我不会费心在纯Java中处理这么长的空检查。好吧,你当然可以这么做。它将使代码更具可读性。根据问题,使用try-catch-blog并没有那个么昂贵。那个些对象中有多少可能是空的?如果它根本不可能(甚至是例外),那么这就是例外的目的。然而,我认为如果这些对象经常是空的(根据设计),那么捕获异常的成本将比完全避免异常的成本更高。如果你的应用程序不是性能关键型的,我不会担心。不过我会尝试捕捉特定的异常。不要把所有的事情都归为异常,这不是一个好的做法,最终会伤害到你。