Java:检查null或允许异常处理
我想知道使用try/exception来处理空值比使用if语句首先检查空值要花多少钱 提供更多信息。有超过50%的几率获得空值,因为在这个应用程序中。如果未输入数据,则通常为空。。。因此,尝试使用空值进行计算是很常见的 也就是说,如果我在计算之前先使用if语句检查null,而不首先尝试计算,那么它会提高性能吗?或者只让抛出异常并处理异常会降低成本吗 谢谢你的建议:-)Java:检查null或允许异常处理,java,Java,我想知道使用try/exception来处理空值比使用if语句首先检查空值要花多少钱 提供更多信息。有超过50%的几率获得空值,因为在这个应用程序中。如果未输入数据,则通常为空。。。因此,尝试使用空值进行计算是很常见的 也就是说,如果我在计算之前先使用if语句检查null,而不首先尝试计算,那么它会提高性能吗?或者只让抛出异常并处理异常会降低成本吗 谢谢你的建议:-) 感谢您的宝贵反馈!下面是一个伪代码示例来澄清原始问题: BigDecimal value1 = null //assume va
感谢您的宝贵反馈!下面是一个伪代码示例来澄清原始问题:
BigDecimal value1 = null //assume value1 came from DB as null
BigDecimal divisor = new BigDecimal("2.0");
try{
if(value1 != null){ //does this enhance performance?... >50% chance that value1 WILL be null
value1.divide(divisor);
}
}
catch (Exception e){
//process, log etc. the exception
//do this EVERYTIME I get null... or use an if statement
//to capture other exceptions.
}
我建议检查null,不要进行计算,而不要抛出异常 异常应该是“异常”和罕见的,而不是管理控制流的方法
我还建议您与客户就输入参数签订合同。如果允许为空,请详细说明;如果没有,请说明应该传递什么、默认值以及如果传递空值,您承诺返回什么。如果获得空值的几率大于50%,那么这几乎不是例外
就我个人而言,我想说,如果你期望发生什么事情,你应该为它编写适当的代码——在这种情况下,检查null并做任何适当的事情。我一直认为抛出异常的代价不太便宜,但不能肯定。如果传递
null
参数是一种例外情况,那么我会抛出NullPointerException
public Result calculate(Input input) {
if (input == null) throw new NullPointerException("input");
// ...
}
如果允许传递
null
,那么我将跳过计算,最终返回null
。但在我看来,这没什么意义。在第一个实例中传递null
似乎是调用代码中的一个错误
无论您选择哪种方式,都应该在Javadoc中正确地记录它,以避免API用户感到意外。Try-and-catch接近“免费”,但抛出可能非常昂贵。通常VM创建者不会优化异常路径,因为它们是异常的(应该很少) NullPointerException表示程序员错误(RuntimeException),不应被捕获。您不应该捕获NullPointerException,而应该修复代码,使异常不会首先抛出 更糟糕的是,如果您捕获了NullPointerException,并且计算代码中抛出NullPointerException的部分与您期望抛出的部分不同,那么您现在已经掩盖了一个bug
为了完全回答您的问题,我将以一种方式实现它,对其进行概要分析,然后以另一种方式实现它并对其进行概要分析。。。然后,我只使用if语句,避免抛出NullPointerException,而不管哪一个更快,这仅仅是因为上面的一点。我同意大多数其他回答,即您应该更喜欢null检查而不是try-catch。我已经把他们中的一些投了更高的票 但是你应该尽量避免这种需要 有超过50%的几率获得空值,因为在这个应用程序中。如果未输入数据,则通常为空。。。因此,尝试使用空值进行计算是很常见的 这才是你真正应该解决的问题 提出合理的默认值,以确保计算正常进行,或避免在不提供所需输入数据的情况下调用计算
对于许多标准数据类型和涉及它们的计算,都有合理的默认值。根据其含义,默认数字为0或1,默认字符串和集合为空,并且许多计算都可以正常工作。对于你自己制作的更复杂的对象,请考虑这个模式。 如果你有任何结果或输入不能被程序处理,那么这应该是一个错误。您应该知道您的程序可以处理什么,并且只允许它。对于未来可能出现的情况,如果结果可以处理,但尚未处理,我仍然建议将其视为错误,直到您真正需要该结果。如果有疑问,你不知道,程序不知道,它无法处理,你没有装备你的程序来处理它,所以这是一个错误。这个程序除了停止外,什么也做不了 对于用户输入来说,依赖程序最终崩溃是一个非常糟糕的主意。你不知道它什么时候甚至是否会崩溃。它可能只是做了错误的事情,或者做了十件事情,然后崩溃,这是它不应该做的,如果输入被验证的话也不会做的 就防止自己的错误而言,这是一个复杂的问题。通过测试、消除未知因素、校对、确保准确了解程序的工作方式等,您将需要更多地关注确保工作正常。不过,偶尔也会出现内部处理可能产生不希望的结果的情况 当结果不是给定情况下的错误时,您不处理异常,而是处理null,而不是异常。在这种情况下,结果不是错误。所以你要处理结果而不是错误。再简单不过了。如果您正在捕获异常,然后执行可以使用If执行的操作,例如:
try
extra = i_need_it(extra_id)
show('extra', extra)
catch
show('add_extra')
Object i_want(Object it) throws
if(it === null)
throw
return it;
那就不对了。如果你没有多余的东西,你有一个完全可以接受的行动方案
这样做更好,而且可以让您的意图更加清晰,而不需要额外的赘述:
Something extra = i_want_it(extra_id)
if extra ==== null
show('add_extra')
else
show('extra', extra)
注意,这里您不需要任何特殊的东西来避免捕获另一层的异常。我怎么把试球放在上面是一个坏习惯。您应该只包装引发异常的对象:
Something extra
try
extra = i_need_it(extra_id)
if extra === null
show('add_extra')
else
show('extra', extra)
当你这样想的时候,它只是将null转换为exception,然后再转换回来。这是溜溜球编码
您应该从以下内容开始:
Object i_need_it(int id) throws
直到你
bool does_it_exist(int id)
if(does_it_exist(id))
Something i_need = i_need_it(id)
void it_must_exist(int id) throws
Object|null get(int id, bool require) throws
Object i_want(Object it) throws
if(it === null)
throw
return it;
void give_me(Object it)
this.it = Lib<Object>::i_want(it)
void i_get_it(Getter<Object> g)
this.it = Lib<Object>::i_want(g.gimme())
void i_need_it(Result<Object> r)
this.it = r.require()
void i_need_it(Object it)
this.it = it
void i_want_it(Object? it)
this.it = it