为什么不同的Java 7和Java 8之间isAnnotation present工作? [英] Why does isAnnotationPresent work differently between Java 7 and Java 8?

查看:1982
本文介绍了为什么不同的Java 7和Java 8之间isAnnotation present工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚发现今天这个时候,我的单元测试有一个失败,因为升级从Java 7到Java 8单元测试调用它试图找到其中的一个子类,但有注释的方法的注释的方法不同的返回类型。

在Java 7中, isAnnotation present 似乎只能找到注解,如果他们在code真的声明。在Java 8, isAnnotation present 似乎包括儿童类被声明注释。

为了说明这一点,我创建了一个简单(??)测试类IAPTest(为IsAnnotation presentTest)。

 进口java.lang.annotation.Retention;
进口java.lang.annotation.RetentionPolicy;
进口的java.lang.reflect.Method;公共类IAPTest {
    @Retention(RetentionPolicy.RUNTIME)
    公共静态@interface安诺{
    }
    公共静态接口I {
    }
    公共静态界面IE扩展I {
    }
    公共静态类A {
        保护我的方法(){
            返回null;
        }
    }
    公共静态类B扩展A {
        @Anno
        IE保护法(){
            返回null;
        }
    }
    公共静态无效的主要(字串[] args){
        针对(法方法:B.class.getDeclaredMethods()){
            如果(method.getName()等于(方法)及&放大器; I.class.equals(method.getReturnType())){
                的System.out.println(method.isAnnotation present(Anno.class));
            }
        }
    }
}

在最新的Java 7(1.7.0_79在写作时),这种方法打印假。在最新的Java 8(1.8.0_66在写作时),这种方法打印真。我会直觉地期望它打印假。

这是为什么?这是否表明Java或错误在Java中是如何工作的预期变化?

修改:只是为了显示我用这个复制(与IAPTest.java目录等同于code以上块),精确的命令:

  C:\\测试isannotation present>德尔的* .classC:\\测试isannotation present>设置JAVA_HOME = C:\\ NMA \\工具集\\ AJB1 \\ OracleJDK \\ jdk1.8.0_66C:\\测试isannotation present>设置PATH =%PATH%; C:\\ NMA \\工具集\\ AJB1 \\ OracleJDK \\ jdk1.8.0_66 \\ BINC:\\测试isannotation present> Java的版本
Java版本1.8.0_66
的Java(TM)SE运行时环境(建立1.8.0_66-B17)
Java的热点(TM)64位服务器VM(25.66建设-B17,混合模式)C:\\测试isannotation present>的javac IAPTest.javaC:\\测试isannotation present>的java IAPTest
真正C:\\测试isannotation present>


解决方案

我相信这是关系到在的 Java的8兼容性指南


  

从此版本开始,参数和方法的注释被复制到
  合成桥methods.This修复意味着,现在这样的程序:

  @Target(价值= {} ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)@interface ParamAnnotation {}
@Target(价值= {} ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)@interface MethodAnnotation {}
抽象类T< A,B> {
    B M(A一){
        返回null;
    }
}
类CovariantReturnType扩展T<整数,整数GT; {
    @MethodAnnotation
    整数米(@ParamAnnotation整数I){
        返回我;
    }    公共类VisibilityChange扩展CovariantReturnType {}
}

每个生成的电桥法将拥有的所有注释
  方法将其重定向到。参数说明也将被复制。
  这种变化的行为可能影响一些注解处理器或
  一般来说任何应用程序使用该注释。


这是返回一个第二个方法我代替 IE 是生成的,因为你有一个窄的合成方法在重写的方法返回类型比超类。请注意,这不是在声明的方法列表present如果你没有缩小返回类型。所以我觉得这是不是一个错误,而是一种蓄意的变化。

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>

解决方案

I believe this is related to a change mentioned in the 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.

The second method that returns an I instead of an IE is a synthetic method generated because you have a narrower return type in the overridden method than in the super class. Note that it's not present in the list of declared methods if you don't have a narrowing return type. So I think this is not a bug, but a deliberate change.

这篇关于为什么不同的Java 7和Java 8之间isAnnotation present工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆