问题描述
我相信这与Java 8兼容性指南中提到的更改有关
从此版本开始,参数和方法注释将复制到合成桥方法。此修复程序意味着现在对于以下程序:
@Target(value = {ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @interface ParamAnnotation {} @Target(value = {ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MethodAnnotation {} abstract class T<A,B> { B m(A a){ return null; } } class CovariantReturnType extends T<Integer, Integer> { @MethodAnnotation Integer m(@ParamAnnotation Integer i) { return i; } public class VisibilityChange extends CovariantReturnType {} }
每个生成的桥方法将具有其重定向到的方法的所有注释。参数注释也将被复制。行为的这种变化可能会影响某些注释处理器,或者通常会影响使用注释的任何应用程序。
第二个返回an I
而不是anIE
的方法是生成的合成方法,因为您覆盖的方法中的返回类型比父类中的返回类型窄。请注意,如果您没有缩小的返回类型,则它不在声明的方法列表中。所以我认为这不是错误,而是有意的更改。
解决方法
今天,我刚刚发现了一个问题,因为我的一个单元测试由于从Java 7升级到Java
8而失败了。该单元测试调用一个方法,该方法试图在子类上注释的方法上找到注释,但返回类型不同。
在Java 7中,isAnnotationPresent
似乎只有在代码中确实声明了注释时,才会找到注释。在Java
8中,isAnnotationPresent
似乎包含在子类中声明的注释。
为了说明这一点,我创建了一个简单的(??)测试类IAPTest(用于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));
}
}
}
}
在最新的Java 7(撰写本文时为1.7.0_79)上,此方法显示“ false”。在最新的Java 8(撰写本文时为1.8.0_66)上,此方法显示“
true”。我直觉上希望它打印“ false”。
为什么是这样?这是否表示Java中的错误或Java工作方式的预期变化?
编辑 :只是为了显示我用来复制它的确切命令(在与上面的代码块相同的IAPTest.java目录中):
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>