Java:如何有效地检查空指针 [英] Java: How to check for null pointers efficiently

查看:195
本文介绍了Java:如何有效地检查空指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一些模式用于检查方法的参数是否已赋予 null 值。



首先,经典之一。这是常见的自制代码和明显的理解。

  public void method1(String arg){
if (arg == null){
throw new NullPointerException(arg);
}
}

其次,可以使用现有框架。该代码看起来更好一点,因为它只占用一行。缺点是,它可能调用另一个方法,这可能会使代码运行一点慢,这取决于编译器。

  public void method2(String arg){
Assert.notNull(arg,arg);
}

第三,可以尝试调用对对象没有副作用的方法。这可能看起来很奇怪,但它比上面的版本更少令牌。

  public void method3(String arg){
arg.getClass();
}



我没有看到第三种模式广泛使用,感觉几乎好像我自己发明了它。我喜欢它的短缺,并且因为编译器有一个很好的机会完全优化它或将其转换为一个单一的机器指令。我也编译我的代码与行号信息,所以如果一个 NullPointerException 抛出,我可以追溯到确切的变量,因为我只有一个这样的检查每行。



您喜欢哪一种检查?为什么?

解决方案

strong> 方法3: arg.getClass(); 很聪明,但除非这个习语广泛采用,否则喜欢更清晰,更冗长的方法,而不是保存几个字符。我是一个写一次,读多少的程序员。



其他方法是自我记录:有一个日志消息,你可以用来澄清发生了什么 - 这个日志消息是在读取代码时以及在运行时使用的。 arg.getClass(),因为它是,不是自我记录。您至少可以使用注释来澄清代码的审查者:

  arg.getClass(); // null check 

但是你还是没有机会在运行时






方法#1 vs#2 + NPE / IAE vs assert): 我尝试遵循以下指南:



http://data.opengeo.org/GEOT-290810-1755-708.pdf




  • 使用 assert 检查私人方法的参数

    assert param> 0;


  • 使用null检查+ IllegalArgumentException 公共方法的参数

    if(param == null)throw new IllegalArgumentException(param can not be null);



  • if(getChild()== null )throw new NullPointerException(node must have children);







,因为这可能是关于最有效地捕获潜在 null 问题的问题,那么我必须提到我的首选方法来处理 null 正在使用静态分析,例如类型注释(例如 @NonNull )a JSR-305 。我最喜欢的检查它们的工具是:



Checker框架:

Java的自定义可插入类型

http://types.cs.washington.edu/checker-framework/current/checkers- manual.html#checker-guarantee



如果我的项目(例如不是一个带有公共API的库),并且我可以使用Checker框架:




  • 我可以在API中更清楚地记录我的意图(例如,此参数可能不为null一个可能是null( @Nullable ;方法可能返回null;等)。这个注释是在声明,而不是更远的Javadoc,所以更多


  • 静态分析会提前标记潜在的逻辑缺陷(例如我试图传递一个变量,可能为null的方法,只接受一个非null参数),而不是根据发生在运行时出现的问题。




另外一个好处是,工具让我把注释放在注释中(例如`/ @ Nullable /),所以我的库代码可以兼容类型 - 注释项目和非类型注释项目(不是我有任何这些项目)。








http://data.opengeo.org/GEOT-290810-1755-708.pdf



5.1.7使用断言,IllegalArgumentException和NPE



Java语言已经有几年了assert关键字可用;此关键字可用于执行仅调试检查。
虽然这个工具有多种用途,一个常见的方法是在私有(而不是公共)方法上检查方法参数。其他用途是
后置条件和不变量。



参考: 使用断言进行编程



前提条件方法)通常是断言的容易的目标。后条件和不变量有时不太直观,但更有价值,因为不平凡的条件有更多的风险被打破。




  • 示例1:在引用模块中的地图投影之后,断言执行逆映射投影并检查结果
    与原点(后置条件)。

  • 示例2:在DirectPosition.equals(Object)实现中,如果结果为true,则断言确保
    hashCode()与Object

  • $ b

    $ b

      private double scale(int scaleDenominator){
    assert scaleDenominator> 0;
    return 1 /(double)scaleDenominator;
    }

    您可以使用以下命令行参数启用断言:

      java -ea MyApp 

    您可以使用以下命令行参数只转换GeoTools断言:

      java -ea:org.geotools MyApp 

    您可以禁用特定包的断言,如下所示:

      java -ea:org.geotools -da:org.geotools.referencing MyApp 

    使用IllegalArgumentExceptions检查公共方法的参数



    严格禁止在公共方法上使用断言;因为报告的错误是在客户端代码中进行的 - 诚实,并且
    当他们崩溃时告诉他们一个IllegalArgumentException。

      public double toScale(int scaleDenominator){
    if(scaleDenominator> 0){
    throw new IllegalArgumentException(scaleDenominator must be big than 0);
    }
    return 1 /(double)scaleDenominator;
    }

    在需要时使用NullPointerException b
    $ b

    如果可能,请执行您自己的空检查;抛出一个IllegalArgumentException或NullPointerException与详细信息
    关于什么问题。

      public double toScale(Integer scaleDenominator){ 
    if(scaleDenominator == null){
    throw new NullPointerException(scaleDenominator must be provided);
    }
    if(scaleDenominator> 0){
    throw new IllegalArgumentException(scaleDenominator must be大于0);
    }
    return 1 /(double)scaleDenominator;
    }


    There are some patterns for checking whether a parameter to a method has been given a null value.

    First, the classic one. It is common in self-made code and obvious to understand.

    public void method1(String arg) {
      if (arg == null) {
        throw new NullPointerException("arg");
      }
    }
    

    Second, you can use an existing framework. That code looks a little nicer because it only occupies a single line. The downside is that it potentially calls another method, which might make the code run a little slower, depending on the compiler.

    public void method2(String arg) {
      Assert.notNull(arg, "arg");
    }
    

    Third, you can try to call a method without side effects on the object. This may look odd at first, but it has fewer tokens than the above versions.

    public void method3(String arg) {
      arg.getClass();
    }
    

    I haven't seen the third pattern in wide use, and it feels almost as if I had invented it myself. I like it for its shortness, and because the compiler has a good chance of optimizing it away completely or converting it into a single machine instruction. I also compile my code with line number information, so if a NullPointerException is thrown, I can trace it back to the exact variable, since I have only one such check per line.

    Which check do you prefer, and why?

    解决方案

    Approach #3: arg.getClass(); is clever, but unless this idiom see widespread adoption, I'd prefer the clearer, more verbose methods as opposed to saving a few characters. I'm a "write once, read many" kind of programmer.

    The other approaches are self-documenting: there's a log message you can use to clarify what happened - this log message is use when reading the code and also at run-time. arg.getClass(), as it stands, is not self-documenting. You could use a comment at least o clarify to reviewers of the code:

    arg.getClass(); // null check
    

    But you still don't get a chance to put a specific message in the runtime like you can with the other methods.


    Approach #1 vs #2 (null-check+NPE/IAE vs assert): I try to follow guidelines like this:

    http://data.opengeo.org/GEOT-290810-1755-708.pdf

    • Use assert to check parameters on private methods
      assert param > 0;

    • Use null check + IllegalArgumentException to check parameters on public methods
      if (param == null) throw new IllegalArgumentException("param cannot be null");

    • Use null check + NullPointerException where needed
      if (getChild() == null) throw new NullPointerException("node must have children");


    HOWEVER, since this is question may be about catching potential null issues most efficiently, then I have to mention my preferred method for dealing with null is using static analysis, e.g. type annotations (e.g. @NonNull) a la JSR-305. My favorite tool for checking them is:

    The Checker Framework:
    Custom pluggable types for Java
    http://types.cs.washington.edu/checker-framework/current/checkers-manual.html#checker-guarantees

    If its my project (e.g. not a library with a public API) and if I can use the Checker Framework throughout:

    • I can document my intention more clearly in the API (e.g. this parameter may not be null (the default), but this one may be null (@Nullable; the method may return null; etc). This annotation is right at the declaration, rather than further away in the Javadoc, so is much more likely to be maintained.

    • static analysis is more efficient than any runtime check

    • static analysis will flag potential logic flaws in advance (e.g. that I tried to pass a variable that may be null to a method that only accepts a non-null parameter) rather than depending on the issue occurring at runtime.

    One other bonus is that the tool lets me put the annotations in a comment (e.g. `/@Nullable/), so my library code can compatible with type-annotated projects and non-type-annotated projects (not that I have any of these).


    In case the link goes dead again, here's the section from GeoTools Developer Guide:

    http://data.opengeo.org/GEOT-290810-1755-708.pdf

    5.1.7 Use of Assertions, IllegalArgumentException and NPE

    The Java language has for a couple of years now made an assert keyword available; this keyword can be used to perform debug only checks. While there are several uses of this facility, a common one is to check method parameters on private (not public) methods. Other uses are post-conditions and invariants.

    Reference: Programming With Assertions

    Pre-conditions (like argument checks in private methods) are typically easy targets for assertions. Post-conditions and invariants are sometime less straighforward but more valuable, since non-trivial conditions have more risks to be broken.

    • Example 1: After a map projection in the referencing module, an assertion performs the inverse map projection and checks the result with the original point (post-condition).
    • Example 2: In DirectPosition.equals(Object) implementations, if the result is true, then the assertion ensures that hashCode() are identical as required by the Object contract.

    Use Assert to check Parameters on Private methods

    private double scale( int scaleDenominator ){
     assert scaleDenominator > 0;
     return 1 / (double) scaleDenominator;
    }
    

    You can enable assertions with the following command line parameter:

    java -ea MyApp
    

    You can turn only GeoTools assertions with the following command line parameter:

    java -ea:org.geotools MyApp
    

    You can disable assertions for a specific package as shown here:

    java -ea:org.geotools -da:org.geotools.referencing MyApp
    

    Use IllegalArgumentExceptions to check Parameters on Public Methods

    The use of asserts on public methods is strictly discouraged; because the mistake being reported has been made in client code - be honest and tell them up front with an IllegalArgumentException when they have screwed up.

    public double toScale( int scaleDenominator ){
     if( scaleDenominator > 0 ){
     throw new IllegalArgumentException( "scaleDenominator must be greater than 0");
     }
     return 1 / (double) scaleDenominator;
    }
    

    Use NullPointerException where needed

    If possible perform your own null checks; throwing a IllegalArgumentException or NullPointerException with detailed information about what has gone wrong.

    public double toScale( Integer scaleDenominator ){
     if( scaleDenominator == null ){
     throw new NullPointerException( "scaleDenominator must be provided");
     }
     if( scaleDenominator > 0 ){
     throw new IllegalArgumentException( "scaleDenominator must be greater than 0");
     }
     return 1 / (double) scaleDenominator;
    }
    

    这篇关于Java:如何有效地检查空指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆