【问题标题】:Java Null Reference Best PracticeJava Null 参考最佳实践
【发布时间】:2011-08-24 21:45:07
【问题描述】:

在 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
}

【问题讨论】:

    标签: java coding-style


    【解决方案1】:

    已经给出的答案非常好(不要将异常用于控制流;异常的抛出和处理成本很高)。还有另外一个重要的原因,特别是不要抓住NullPointerException

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

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

    这似乎是处理reference 的无效性的一种安全方法……但是如果引用是非null 并且someMethod() 引发了NPE,该怎么办?或者如果在 try 块的其他地方提出了 NPE 怎么办?捕获 NPE 是防止错误被发现和修复的可靠方法。

    【讨论】:

      【解决方案2】:

      捕获异常的成本相对较高。通常最好是发现情况而不是对其做出反应。

      【讨论】:

      • 谢谢。我想“为什么当 JVM 为我检查 null 时,我可以使用该检查”,但如果捕获它是如此昂贵,我将自己进行检查。再次感谢!
      【解决方案3】:

      当然是这个

      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 方法中。

      【讨论】:

        【解决方案4】:

        我认为通常应该为特殊情况保留一个异常 - 如果有时需要空引用,您应该检查它并明确处理它。

        【讨论】:

          【解决方案5】:

          从答案中可以清楚地看出,捕获异常并不好。 :) 例外绝对不是免费的。 This might help you to understand it in depth..

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

          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.
          }
          

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

              第一种形式:

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

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

              异常用于处理在正常操作条件下通常不会发生的异常情况。

              【讨论】:

                【解决方案8】:

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

                【讨论】:

                  【解决方案9】:

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

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

                  【讨论】:

                  • 不是真的,你仍然在抛出一个不必要的异常。更好地使用if (reference == null) { // create new reference retry; }
                  【解决方案10】:

                  这和你的开发风格有关,如果你使用“安全”风格开发代码,你必须使用

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

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

                  【讨论】:

                    【解决方案11】:

                    由于您要求提供最佳实践,我想指出Martin Fowler 建议为空引用引入一个子类作为最佳实践。

                    public class NullCustomer extends Customer {}
                    

                    因此,您避免了处理未经检查的 NullPointerException 的麻烦。可能返回客户值为 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 );
                    }
                    

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

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2017-04-06
                      • 1970-01-01
                      • 2016-07-03
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多