BadAnnotationImplementation
Classes that implement Annotation must override equals and hashCode. Consider using AutoAnnotation instead of implementing Annotation by hand.

Severity
ERROR

The problem

Implementations of Annotation must override equals and hashCode to match the expectations defined in that interface, to ensure compatibility with the annotation instances that source annotations create. Without this, operations that care about equality of annotations (such as qualified dependency injection bindings) will fail in mysterious ways.

class Foo {
  @SomeAnnotation("hello") public void annotatedMethod() {}

  private static class HelloAnnotationImpl implements SomeAnnotation {
    @Override
    public Class<? extends Annotation> annotationType() {
      return SomeAnnotation.class;
    }

    @Override
    public String value() {
      return "hello";
    }
  }

  static void test() {
    Annotation manual = new HelloAnnotationImpl();
    Annotation fromMethod = Foo.class.getMethod("annotatedMethod").getDeclaredAnnotations()[0];

    manual.equals(fromMethod); // false, violating equality expectations of Annotation!
  }
}

It is very difficult to write these methods correctly, so consider using @AutoAnnotation to generate a properly-functioning implementation of Annotation:

class Foo {
  @SomeAnnotation("hello") public void annotatedMethod() {}

  @AutoAnnotation
  private static SomeAnnotation someAnnotationInstance(String value) {
    return new AutoAnnotation_Foo_someAnnotationInstance(value);
  }

  static void test() {
    Annotation manual = someAnnotationInstance("hello");
    Annotation fromMethod = Foo.class.getMethod("annotatedMethod").getDeclaredAnnotations()[0];

    manual.equals(fromMethod); // true, hooray!
  }
}

Suppression

Suppress false positives by adding the suppression annotation @SuppressWarnings("BadAnnotationImplementation") to the enclosing element.