2

I started using findbugs @Nonnull and @CheckForNull annotations on an existing Project, to prevent NPEs, and think it works quite nice. I use @Nonnull as default for return types and parameters and found already a few NPEs, just by adding the default values. Now I found a method similar to this:

@Nonnull
private Integer getInteger(String key) {
    return Map.get(key);
}

And it does not produce a warning. I understand why this is the case, but how can I get around this? How do you work around this in your projects?

A solution that can be globally applied would be preferred, e.g. something like @ApplyCheckForNullToAllExternalCalls.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
Thomas M.
  • 1,496
  • 1
  • 10
  • 21

1 Answers1

1

You can apply @CheckForNull to all method return values (and/or parameters) within a package by adding the annotation to the package's package-info.java file, but you won't have control over individual methods.

First, create @ReturnValuesAreCheckForNullByDefault in a utility package of your project.

@Documented
@CheckForNull
@TypeQualifierDefault(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ReturnValuesAreCheckForNullByDefault { /* noop */ }

Next, create src/java/util/package-info.java.

@ReturnValuesAreCheckForNullByDefault
package java.util;

import my.project.util.ReturnValuesAreCheckForNullByDefault;

Finally, enjoy your FindBugs warnings.

@Nonnull
public String getValue() {
    Map<String, String> values = new HashMap<>();
    return values.get("foo");    // <-- Possible null pointer dereference ...
}

The problem with doing this is that there are many methods in the java.* packages that contractually do not return null. Using these without checking for null will raise warnings. For example, this NPE-safe code also raises a warning:

@Nonnull
public Set<String> getNotNull() {
    Map<String, String> values = new HashMap<>();
    return values.keySet();
}

You can suppress the warning with @SuppressFBWarnings, but this may clutter up the code too much for your liking.

David Harkness
  • 35,992
  • 10
  • 112
  • 134
  • How does Findbugs know about `@ReturnValuesAreCheckForNullByDefault`? I mean, how does FB know how to interpret your custom annotation? – barfuin Jan 08 '13 at 07:56
  • [`TypeQualifierDefault`](http://jsr-305.googlecode.com/svn/trunk/javadoc/javax/annotation/meta/TypeQualifierDefault.html) is part of JSR-305 and causes the other annotations to be carried over to the elements (methods, parameters, fields, etc. depending on its parameter) annotated with the annotation to which it is attached. See [`ParametersAreNonnullByDefault`](http://jsr-305.googlecode.com/svn/trunk/javadoc/javax/annotation/ParametersAreNonnullByDefault.html) for an example from JSR-305, nearly identical to the above. – David Harkness Jan 08 '13 at 10:52
  • Thanks, I knew the package-info.java, but didn't think of writing one for a package outside of my control. However, I think you're right, that not being able to make certain Util-methods @Nonnull will be quite annoying. – Thomas M. Jan 08 '13 at 11:00