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 {
}
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.
Default methods were introduced to provide backward compatibility for old interfaces so that they can have new methods without affecting existing code.
A default method cannot override a method from 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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With