I just discovered this today when one of my unit tests failed because of upgrading from Java 7 to Java 8. The unit test calls a method which tries to find an annotation on a method which is annotated on a child class but with a different return type.
In Java 7, isAnnotationPresent
seems to only find annotations if they were really declared in code. In Java 8, isAnnotationPresent
seems to include annotations that were declared in child classes.
To illustrate this I created a simple (??) test class IAPTest (for IsAnnotationPresentTest).
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
public class IAPTest {
@Retention(RetentionPolicy.RUNTIME)
public static @interface Anno {
}
public static interface I {
}
public static interface IE extends I {
}
public static class A {
protected I method() {
return null;
}
}
public static class B extends A {
@Anno
protected IE method() {
return null;
}
}
public static void main(String[] args) {
for (Method method : B.class.getDeclaredMethods()) {
if (method.getName().equals("method") && I.class.equals(method.getReturnType())) {
System.out.println(method.isAnnotationPresent(Anno.class));
}
}
}
}
On the latest Java 7 (1.7.0_79 at time of writing), this method prints "false". On the latest Java 8 (1.8.0_66 at time of writing), this method prints "true". I would intuitively expect it to print "false".
Why is this? Does this indicate a bug in Java or an intended change in how Java works?
EDIT: Just to show the exact commands I used to replicate this (in a directory with IAPTest.java identical to the code block above):
C:\test-isannotationpresent>del *.class
C:\test-isannotationpresent>set JAVA_HOME=C:\nma\Toolsets\AJB1\OracleJDK\jdk1.8.0_66
C:\test-isannotationpresent>set PATH=%PATH%;C:\nma\Toolsets\AJB1\OracleJDK\jdk1.8.0_66\bin
C:\test-isannotationpresent>java -version
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)
C:\test-isannotationpresent>javac IAPTest.java
C:\test-isannotationpresent>java IAPTest
true
C:\test-isannotationpresent>