Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use FindBugs’ @CheckForNull, @Nonnull and @Nullable annotations correctly

I would like to formally annotate my function signatures to clarify their contracts—especially if null params and return values are permitted or prohibited—in a way that FindBugs’ static code analysis tool (and maybe other) can make use of it.

There are two packages (annotations.jar and jsr305.jar) with four annotations each to achieve this, as well as the option not to put an annotation at all.

like image 846
Matthias Ronge Avatar asked Jul 01 '15 09:07

Matthias Ronge


2 Answers

These are my findings after some trying around:

Method parameters:

  • Parameter must not be null: Do not put any annotation. In this case a bug marker appears if null is passed to the method. (I had expected this behaviour when putting the @Nonnull annotation, but when I put it, no bug marker came up at all.)
  • Parameter can be null: Put @Nullable annotation. (Same effect for @CheckForNull. The @Nullable documentation reads: “FindBugs will treat the annotated items as though they had no annotation.” This is not true. If I call string.length() and String string has been marked @Nullable, it causes a bug marker to appear, if there is no annotation no bug marker showed.)

Method return value:

  • Method never returns null: Put @Nonnull. Causes a bug marker if you try to return null; from inside the method.
  • Method can return null: Do you want to enforce checks for it? Checks may be an overhead if the return value does depend on the method parameters only which can be assumed known at call time, like “my method returns null if parameter one is negative”. I would not put an annotation in that case. However, you may want to consider throwing an IllegalArgumentException instead of returning null.
  • Method can return null and the return object should always be checked: Put @CheckForNull. However, in many cases there are better ways to go, you may want to consider returning Collections.emptyList() instead of null lists, or throwing MissingResourceException, IOException or another appropriate exception.

Which JAR file to use:

  • Both jar files cause the same behaviour of FindBugs, the only difference is that the annotations from annotations.jar are showing as deprecated in Eclipse. So use jsr305.jar.
  • The jar file is needed. Creating empty annotations with the given package and class name does not work. You can get it here.
like image 199
Matthias Ronge Avatar answered Sep 19 '22 10:09

Matthias Ronge


@Paramaeleon gave some great tips, such as how you must leave a method parameter unannotated because FindBugs unintuitively suppresses all warnings if you write @Nonnull.

If you are willing to try a different static analysis tool, you might consider the Nullness Checker of the Checker Framework.

The main difference is that the Nullness Checker aims to detect all null pointer errors. By contrast, FindBugs intentionally does not report some possible errors to you, in order to report fewer false positive warnings. Both tools give better results the more annotations you write. If you are not willing to write any annotations, then FindBugs is a more appropriate tool. If you are willing to write annotations, then the Checker Framework may be better.

The Nullness Checker manual contains more comparisons in its section about choosing a nullness analysis tool.

like image 30
mernst Avatar answered Sep 22 '22 10:09

mernst