gpt4 book ai didi

java - 为什么 isAnnotationPresent 在 Java 7 和 Java 8 之间的工作方式不同?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:58:21 25 4
gpt4 key购买 nike

我今天刚刚发现这一点,因为我的一个单元测试由于从 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>

最佳答案

我相信这与 java 8 compatibility guide 中提到的更改有关

As of this release, parameter and method annotations are copied to synthetic bridge methods.This fix implies that now for programs like:

@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 {}
}

Each generated bridge method will have all the annotations of the method it redirects to. Parameter annotations will also be copied. This change in the behavior may impact some annotations processor or in general any application that use the annotations.

返回 I 而不是 IE 的第二个方法是生成的合成方法,因为重写方法中的返回类型比父类(super class)中的返回类型更窄。请注意,如果您没有缩小返回类型,它不会出现在已声明方法的列表中。所以我认为这不是一个错误,而是一个刻意的改变。

关于java - 为什么 isAnnotationPresent 在 Java 7 和 Java 8 之间的工作方式不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33549798/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com