有时,函数在某些情况下会返回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没有一些检查(并且很好),我可以使用其他静态代码分析工具,如FindBugs和CodePro Analytix。两者都未能找到这样的错误。
我试图联系这两个项目,但还没有得到任何答案。对于CodePro,我甚至不确定我是否做对了......事实上,我认为这个项目已经停止(2010年的最新更新......)。
是否有任何工具可以帮助避免此类错误?
无论你作为一名程序员有多好,都会发生这样的事情。
我要求的是通过让日食帮助来克服这个问题的方法。它应该能够警告我,至少在我写在这里的基本例子上。
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,因为它有很多很酷的警告和错误,可以帮助避免错误,但我上面写的内容是不可检测的,甚至不是我所谈到的工具。
许多错误很难找到,没有人是一个不犯错误的完美程序员。即使你知道很多,也不会受到其他人的错误保护。人们甚至无法找到基本代码的错误(请参阅here,here或here,看看您自己能找到错误的程度。这就是为什么有工具可以帮助你。
答案 0 :(得分:4)
考虑在代码中使用@Nullable
和@NonNull
注释。部分它可以解决您的问题。
@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的实际错误消息:
更新:您需要在构建路径中包含带有Eclipse注释的JAR。将鼠标指针移动到无法编译的@NonNull
或@Nullable
注释上(如图所示),然后选择使用默认空注释复制库以构建路径 -
新的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包或第三方注释代码。
单元测试应以互补的方式使用,并将提高代码质量。请参阅此问题,了解您应该考虑的几个好处和原因:
答案 2 :(得分:0)
方法有两种方式表示这种“失败”。返回null或抛出异常,通常在javadoc中指示。返回null本身并不是错误,因为例如HashMap.get(key)
将返回null,如果没有与键关联的值。让HashMap
抛出异常将是一个糟糕的选择。另一方面,如果找不到实体,某些JPA方法将抛出异常(例如,请求一个预期存在的唯一实体)。
想象一下,每次使用HashMap
时,你会有多少警告,eclipse会说“小心,它可能会返回null”。
总而言之:在现实生活中警告这一点并不是非常有用,因为你会因为杂乱而忽略警告。