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

前端之家收集整理的这篇文章主要介绍了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()方法(或者你定义的任何其他方法),并返回该值.

猜你在找的Java相关文章