微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java注释的默认值是否被编译成字节码?

我尝试为 Java字节码实现几个静态分析.他们尝试计算某个方法是否具有特定的属性,例如是一种工厂方法.因为这些分析很难测试,所以我决定写一些Java代码,并用正确的属性直接注释方法.运行分析后,自动检查计算的和注释的属性是否相同是很容易的.

MyAnnotation:

@Retention(RUNTIME)
@Target(METHOD)
public @interface FactoryMethodProperty {

    FactoryMethodKeys value() default FactoryMethodKeys.NonFactoryMethod;
}

示例测试代码

public class PublicFactoryMethod {

    private PublicFactoryMethod(){
        // I'm private
    }

    @FactoryMethodProperty
    public static void newInstanceAfterOtherConstructorCall(){
        new TransFacoryMethod();
        new PublicFactoryMethod();
    }

    @FactoryMethodProperty(FactoryMethodKeys.IsFactoryMethod)
    public static PublicFactoryMethod newInstance(){
        return new PublicFactoryMethod();
    }
}

因为我的测试代码中的大多数方法都不是工厂方法,所以我将认值设置为枚举值“FactoryMethodKeys.NonFactoryMethod”.但是,当我没有将枚举值显式传递给注释时,它不会被编译为字节码.

字节码:

#23 = Utf8               value
  #24 = Utf8               Lorg/opalj/fpa/test/annotations/FactoryMethodKeys;
  #25 = Utf8               IsFactoryMethod

{
  public static void newInstanceAfterOtherConstructorCall();
    descriptor: ()V
    flags: ACC_PUBLIC,ACC_STATIC
    RuntimeVisibleAnnotations:
      0: #16()
    Code:
      stack=1,locals=0,args_size=0
         0: new           #17                 // class factoryMethodTest/TransFacoryMethod
         3: invokespecial #19                 // Method factoryMethodTest/TransFacoryMethod."<init>":()V
         6: new           #1                  // class factoryMethodTest/PublicFactoryMethod
         9: invokespecial #20                 // Method "<init>":()V
        12: return
      LineNumberTable:
        line 49: 0
        line 50: 6
        line 51: 12
      LocalVariableTable:
        Start  Length  Slot  Name   Signature

  public static factoryMethodTest.PublicFactoryMethod newInstance();
    descriptor: ()LfactoryMethodTest/PublicFactoryMethod;
    flags: ACC_PUBLIC,ACC_STATIC
    RuntimeVisibleAnnotations:
      0: #16(#23=e#24.#25)
    Code:
      stack=2,args_size=0
         0: new           #1                  // class factoryMethodTest/PublicFactoryMethod
         3: dup
         4: invokespecial #20                 // Method "<init>":()V
         7: areturn
      LineNumberTable:
        line 55: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
}

我错了什么?为什么认值完全被忽略?

解决方法

它不需要在那里在运行时,JVM构造一个可以检索的注释实例.该实例将使用认值进行初始化,该认值在.class文件中,用于注释本身.这表示为 AnnotationDefault attribute

The AnnotationDefault attribute is a variable-length attribute in the
attributes table of certain method_info structures (§4.6),namely
those representing elements of annotation types. TheAnnotationDefault
attribute records the default value for the element represented by the
method_info structure.

Each method_info structure representing an element of an annotation
type may contain at most one AnnotationDefault attribute. The Java
Virtual Machine must make this default value available so it can be
applied by appropriate reflective APIs
.

你最终会调用注释实例的value()方法(或者你定义的任何其他方法),并返回该值.

原文地址:https://www.jb51.cc/java/126226.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐