繁体   English   中英

Java Null参考最佳实践

[英]Java Null Reference Best Practice

在java中,以下哪一种处理可能为空的引用的方式更为“可接受”? 请注意,空引用并不总是表示错误...

if (reference == null) {
    //create new reference or whatever
}
else {
    //do stuff here
}

要么

try {
    //do stuff here
}
catch (NullPointerException e) {
    //create new reference or whatever
}

已经给出的答案非常好(不要使用控制流的例外;抛出和处理的例外是昂贵的)。 还有另一个重要的原因,特别是没有捕获NullPointerException

考虑执行以下操作的代码块:

try {
    reference.someMethod();
    // Some other code
}
catch (NullPointerException e) {
    // 'reference' was null, right? Not so fast...
}

这似乎是一种处理reference无效的安全方法......但是如果引用是非null而someMethod()引发了NPE呢? 或者如果在try块中的其他位置引发了NPE会怎么样? 捕获NPE是防止错误被发现和修复的可靠方法。

捕获异常相对昂贵。 通常最好是检测条件而不是对它做出反应。

当然是这一个

if (reference == null) {
    //create new reference or whatever
}
else {
    //do stuff here
}

我们不应该依赖于例外的决策,而这些例外根本不是为了这个目的而给出的,它们也很昂贵。


那么如果您没有做出决定并且只是验证初始化变量那么

if (reference == null) {
    //create new reference or whatever
}
//use this variable now safely  

我看到一些自动代码生成器在accessors / getter方法中包装了这个东西。

我认为一般情况下应该为特殊情况保留一个例外 - 如果有时需要空引用,则应检查它并明确处理它。

从答案中可以清楚地看出,抓住异常并不好。 :)例外肯定不是免费的。 这可能有助于您深入理解它。

我还想在将您的对象与已知值进行比较时提及另一种做法。
这是完成这项工作的传统方法:(检查对象是否为null然后进行比较)

Object obj = ??? //We dont know whether its null or not.
if(obj!=null && obj.equals(Constants.SOME_CONSTANT)){
    //your logic
}

但是这样,你不必为你的对象烦恼:

Object obj = ???
if(Constants.SOME_CONSTANT.equals(obj)){  //this will never throw 
                                          //nullpointer as constant can not be null.
}

第一个是抛出异常是一项代价高昂的操作。

第一种形式:

if (reference == null)
{    
    //create new reference or whatever
}
else 
{    
    //do stuff here
}

您不应该使用控制流的异常。

例外情况是处理在正常操作条件下通常不会发生的特殊情况。

您应该使用异常捕获,而不希望出现错误。 如果某些东西可以为null,那么你应该检查一下。

也许在我们可以开始做的时候,try catch方法会在这种情况下开始变得有意义

try {
  //do stuff here
}
catch (NullPointerException e) {
  //create new reference or whatever
  retry;
}

如果您使用必须使用的“安全”样式开发代码,这与您的开发风格有关

    if(null == myInstance){
// some code    
    }else{
// some code
    }

但是如果你不使用这种风格至少应该捕获异常,但在这种情况下它是NullPointerException,我认为最好将输入参数检查为null而不是等待抛出异常。

既然你要求最佳实践,我想指出Martin Fowler建议引入一个空引用的子类作为最佳实践。

public class NullCustomer extends Customer {}

因此,您可以避免处理未经检查的NullPointerException的麻烦。 可能返回Customer值为null的方法将返回NullCustomer而不是null。

你的支票看起来像:

final Customer c = findCustomerById( id );
if ( c instanceof NullCustomer ) {
    // customer not found, do something ...
} else {
    // normal customer treatment
    printCustomer( c );
}

在我看来,在某些情况下允许捕获NullPointerException以避免对空引用的复杂检查并增强代码可读性,例如

private void printCustomer( final Customer c ) {
try {
    System.out.println( "Customer " + c.getSurname() + " " + c.getName() + "living in " +     c.getAddress().getCity() + ", " + c.getAddress().getStreet() );
} catch ( NullPointerException ex ) {
    System.err.println( "Unable to print out customer information.", ex );
}

反对它的一个论点是,通过检查单个成员为空,您可以编写更详细的错误消息,但这通常是没有必要的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM