Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interface method´s annotations are inherited in Java 7 but not in Java 8

I´m migrating from Java 7 to Java 8 and I have met with this change in the language.

I have a Superinterface with an annotated method:

public interface SuperInterface {

  @X
  SuperInterface getSomething();
}

I have a SubInterface with the same annotated method but returning a sub-interface:

public interface SubInterface extends SuperInterface {

  @X
  SubInterface getSomething();
}

When I run this test, it fails in Java 8 but not in Java 7:

import java.lang.reflect.Method;

public class Test {

  public static void main(String[] args) {
    final Method[] methods = SubInterface.class.getMethods();
    for (Method method : methods) {
      if (method.getAnnotations().length == 0) {
        throw new RuntimeException("No annotations found for " + method);
      }
    }
  }
}

Interface method´s annotations are inherited in Java 7 but not in Java 8, is it true?

@X is defined as:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface X {  
}
like image 685
leaqui Avatar asked May 23 '17 13:05

leaqui


People also ask

Are annotations inherited from interface?

If an annotation declaration is marked with @Inherited , then a class that extends another class with this annotation can inherit it. The annotation can be overridden in case the child class has the annotation. Because there is no multiple inheritance in Java, annotations on interfaces cannot be inherited.

Why are there default methods in Java 8?

Default methods were introduced to provide backward compatibility for old interfaces so that they can have new methods without affecting existing code.

Can we override default method of interface Java 8?

A default method cannot override a method from java.

Can we annotate interface in Java?

Annotation gives you the ability to provide additional metadata alongside a Java entity (such as classes, interfaces, fields and methods). This additional metadata, called annotation, can be read and interrelated by the compiler or other utilities. They can also be stored in the class files.


1 Answers

As far as I can tell it should work with at least build 94 of java-8, according to this. Thus this is an eclipse compiler bug (I can't reproduce it with javac).

You are using covariance here and as such there will be two methods generated (one is a bridge):

 for (Method method : methods) {
        if (method.getAnnotations().length == 0) {
            System.out.println("Not present " + method.getName() + " isBridge? " + method.isBridge());
        } else {
            System.out.println("Present :" + method.getName() + " isBridge? " + method.isBridge());
        }
    }

But again this should work, since the bug clearly says : Annotation with run-time retention should be copied by javac to bridge methods.

Output with javac:

Present :getSomething isBridge? false
Present :getSomething isBridge? true

Output with eclipse compiler:

Present :getSomething isBridge? false
Not present getSomething isBridge? true
like image 80
Eugene Avatar answered Oct 05 '22 23:10

Eugene