如何获得由函数返回null引起的NPE警告?

时间:2014-02-07 10:26:50

标签: java eclipse nullpointerexception eclipse-jdt static-code-analysis

背景

有时,函数在某些情况下会返回null,然而无论使用它们的人都不知道它,因此NPE是不可避免的。

例如(并且只是 示例,以显示我正在谈论的内容):

public class Test
  {
  public static void main(final String[] args)
    {
    final int t=0;
    System.out.println("result:"+foo(t).toString()); // no warning here...
    }

  public static String foo(final int t)
    {
    if(t>0)
      return "positive";
    else return null;
    }
  }

问题

Eclipse没有警告这样的事情,它甚至没有在设置上。

只有在不涉及任何功能时才能检测到这些问题(参见下面的编辑)。

不仅如此,我找不到一个说明返回值可以为null的注释。我认为它有相反的结果。

我尝试了什么

所以我认为既然Eclipse没有一些检查(并且很好),我可以使用其他静态代码分析工具,如FindBugsCodePro Analytix。两者都未能找到这样的错误。

我试图联系这两个项目,但还没有得到任何答案。对于CodePro,我甚至不确定我是否做对了......事实上,我认为这个项目已经停止(2010年的最新更新......)。

问题

是否有任何工具可以帮助避免此类错误?


编辑:因为许多人认为只需更改代码就可以解决这个问题,所以考虑在一个庞大的团队中工作,有些人可能会忘记它(每个人都会犯错误)。或者你甚至可能正在开发一个使用SDK(甚至可能是封闭源代码)的项目,它可以在某些情况下返回null,但是没有记录,因为SDK的创建者忘记了它。

无论你作为一名程序员有多好,都会发生这样的事情。

我要求的是通过让日食帮助来克服这个问题的方法。它应该能够警告我,至少在我写在这里的基本例子上。

Eclipse应该可以进行此类检查,就像它可以警告我这个例子一样:

int t=0;
--t;
String s="s";
if(t<0)
  s=null;
System.out.println(s.toString()); // here you will get a warning

当您在Eclipse的设置上启用它时,可以检测到它:

Java-> Compiler-> Errors/Warning-> Potential null pointer access

我喜欢Eclipse,因为它有很多很酷的警告和错误,可以帮助避免错误,但我上面写的内容是不可检测的,甚至不是我所谈到的工具。

许多错误很难找到,没有人是一个不犯错误的完美程序员。即使你知道很多,也不会受到其他人的错误保护。人们甚至无法找到基本代码的错误(请参阅hereherehere,看看您自己能找到错误的程度。这就是为什么有工具可以帮助你。

3 个答案:

答案 0 :(得分:4)

考虑在代码中使用@Nullable@NonNull注释。部分它可以解决您的问题。

更新:从http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-using_null_annotations.htm

复制使用的示例
@NonNull String getString(String maybeString) {
    if (maybeString != null)
        return maybeString;                         // the above null check is required
    else
        return "<n/a>";
}
void caller(String s) {
    System.out.println(getString(s).toUpperCase()); // no null check required
}

更新:@Nullable案例

public @Nullable String getMessage() {
    return System.currentTimeMillis() % 2 != 0
        ? "That's odd..."
        : null;
}

public void showCase() {
    String msg = getMessage();
    if (msg.isEmpty()) { //- Here it yields about possible null access
        //...
    }
}

更新:我环境中的空分析设置:

Eclipse setting for Null Analysis

Eclipse的实际错误消息:

enter image description here

更新:您需要在构建路径中包含带有Eclipse注释的JAR。将鼠标指针移动到无法编译的@NonNull@Nullable注释上(如图所示),然后选择使用默认空注释复制库以构建路径 -

enter image description here

新的JAR应出现在Package Explorer中,编译器应该能够看到它。然后将光标移动到注释并按Ctrl + Space - Eclipse应该找到正确的导入(注意,您可能会在列表中看到两个不同的包 - 从JDT中选择一个) - 并选择它。它应该工作。

答案 1 :(得分:1)

为您的代码编写单元测试:

@Test
public void testFooWithZero() {
    try{
        Test tester = new Test();
        assertEquals("Expect string returned", "positive", tester.foo(0));
    catch(NullPointerException npe) {
        fail("Threw NPE");
    }
}

它们不仅描述了您的预期行为(通常比懒惰的Javadoc更好),它保证您的代码符合您的期望。

为正面和负面情景编写测试,你就是金色。

静态代码分析当然有其好处,但它有其局限性 - 一个常见的情况是如何防止从HashMap或类似集合返回null的get(Object)。 SCA无法在运行时知道集合中的数据。您无法从核心Java包或第三方注释代码。

单元测试应以互补的方式使用,并将提高代码质量。请参阅此问题,了解您应该考虑的几个好处和原因:

Is Unit Testing worth the effort?

答案 2 :(得分:0)

方法有两种方式表示这种“失败”。返回null或抛出异常,通常在javadoc中指示。返回null本身并不是错误,因为例如HashMap.get(key)将返回null,如果没有与键关联的值。让HashMap抛出异常将是一个糟糕的选择。另一方面,如果找不到实体,某些JPA方法将抛出异常(例如,请求一个预期存在的唯一实体)。

想象一下,每次使用HashMap时,你会有多少警告,eclipse会说“小心,它可能会返回null”。

总而言之:在现实生活中警告这一点并不是非常有用,因为你会因为杂乱而忽略警告。

相关问题