19

While I think there should be a general rule for inheriting annotations or not, I'm specifically interested in making FindBugs recognize my rules, so this question is FindBugs specific.

AFAIK, JavaDoc comments are taken from the interface and are ignored at the implementation. Does this concept also apply to annotations like @Nonnull (or @NotNull)?

Given the @Override annotation, it is at least possible to add additional annotations which are not present at the interface.

What will happen in the following cases? Will FindBugs recognize all of them? Which one is the preferred one regarding clean code?

  1. Interface @Nonnull, Implementation @Override
  2. Interface @Nonnull, Implementation @Override, @Nonnull
  3. Interface has no annotation, Implementation @Override,@Nonnull`
mkobit
  • 43,979
  • 12
  • 156
  • 150
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • I suggest that you clarify the question to indicate that you are only interested in FindBugs and not other tools, or to indicate that you are interested in the answer for any nullness-checking tool. – mernst Mar 06 '15 at 11:27
  • 1
    @mernst: There is a finbugs tag and I am asking whether FindBugs will recognize all of them. Where else do you suggest to add a FindBugs reference to make it clear? – Thomas Weller Mar 06 '15 at 12:07
  • The tag says the question is relevant to FindBugs, but just adding a tag does not say that the question is *only* relevant to FindBugs. And most people will read the title and text of your question rather than the tags. – mernst Mar 06 '15 at 13:01
  • @mernst: Since I should [not add it to the title](http://meta.stackexchange.com/a/130208/273478), I have added it as the first sentence of my question. – Thomas Weller Mar 06 '15 at 13:18

2 Answers2

8

Go for option 2:

  1. Interface @Nonnull, Implementation @Override @Nonnull

FindBugs and many other tools such as IDEs do a much better job if they find the annotations in the right places. These annotations are not inherited, as the JLS states at the bottom of this section:

Annotation inheritance only works on classes (not methods, interfaces, or constructors)

So the tools would need to go looking for them on their own. Which some tools do, but even FindBugs does not do it consistently (last I checked).

barfuin
  • 16,865
  • 10
  • 85
  • 132
  • I don't understand why we would put the `@Nonnull` on the interface if it's not going to be inherited, can you elaborate, please? – Robert Bain May 31 '20 at 19:54
  • @RobertBain Well, interfaces define the contract, and nullness requirements are part of the contract. If we didn't put the annotations on the interface, code that works only with the interface wouldn't know. – barfuin Jun 01 '20 at 11:31
4

The annotation on the interface States that all implementations must not return null while the one on the implementation states that it obeys that contract. It is not inherited, nor do I think any are.

The @CheckForNull annotation is definitely not inherited because subclasses are allowed to narrow the nullness of the return type just as they may widen it for the parameters they accept.

interface Credentials {
    @NonNull
    String getPassword();

    void setPassword(@NonNull password);
}

// Allows null password
class GoodCreds implements Credentials {
    // but cannot widen; throw exception for null instead
    @Overrides
    @NonNull
    String getPassword() {...}

    // can widen parameters
    @Overrides
    void setPassword(@CheckForNull password) {...}
}

Note: I'll add matching username accessors to demonstrate bad widening in a BadCreds subclass when I have time later.

David Harkness
  • 35,992
  • 10
  • 112
  • 134