我想使用 FindBugs 创建有关应用程序的报告。
我运行它并没有发现像这样的潜在错误:
public List<String> getListTrace(A object) {
String arg = object.getArg();
...
}
如果对象为空,我的应用程序将关闭。
为什么 FindBugs 不发出警报?
我想使用 FindBugs 创建有关应用程序的报告。
我运行它并没有发现像这样的潜在错误:
public List<String> getListTrace(A object) {
String arg = object.getArg();
...
}
如果对象为空,我的应用程序将关闭。
为什么 FindBugs 不发出警报?
Findbugs 不知道 object 是否允许为空。您可以通过使用注释来告诉它:
import javax.annotation.Nullable;
...
public List<String> getListTrace(@Nullable A object) {
这告诉 Findbugs(和阅读代码的人)可以将 null 作为参数传递给 getListTrace。因此,如果您取消引用对象而不检查 null,Findbugs 会警告您。
该代码看起来没有错误。
如果您更改代码以检查是否object
为空,您会怎么做?最合理的动作可能是抛出一个NullPointerException
,对吧?
这正是您的代码片段所做的;它只是让java在访问方法时自动进行测试。
此函数不检查空指针不是错误。如果有人将空指针传递给您的函数并且没有准备好引发NullPointerException
.
Findbug 无法检测潜在的空指针访问。但是,如果您在首选项中激活相应的编译器警告,Eclipse 会针对潜在的空指针访问向您发出警告。
在这种情况下提出错误报告会导致非常大的噪音。您会在完全正确的代码中收到数千条不相关的错误消息。实际上 FindBugs 做了更聪明的事情。如果它发现该方法在没有进行空检查的情况下取消引用该参数,它会在内部将此方法参数标记为@Nonnull
. 如果您有TimK
与此相矛盾的明确注释(如答案),您将收到警告。否则 FindBugs 假定没有人使用此方法和可能为空的参数。当有人实际这样做时,您会在呼叫站点上收到相应的警告。这是一个例子:
import java.util.Collections;
import java.util.List;
public class FBNull {
static class A {
String getArg() {
return "str";
}
}
public static List<String> getListTrace(A object) {
String arg = object.getArg();
return Collections.singletonList(arg);
}
public void callSite(A a) {
if (a == null) {
System.out.println("a is null");
}
System.out.println(getListTrace(a)); // NP_NULL_PARAM_DEREF
}
}
从 FindBugs 的观点来看getListTrace()
方法是可以的。但是该callSite
方法有一个错误。它显式检查其参数null
,因此由于应用程序逻辑,它可能为空。但是,它稍后被传递给getListTrace()
which 立即取消引用该参数。因此,您在方法中有一个错误警告getListTrace()
说:
getListTrace(FBNull$A)
错误:为in的非空参数传递空值FBNull.callSite(FBNull$A)
此方法调用为非空方法参数传递空值。要么将参数注释为应始终为非空的参数,要么分析表明它将始终被取消引用。
因此,如果您实际上可以传递空值,则可以在调用站点上检测到它。