我尝试为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, locals=0, 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
}
我错了什么?为什么完全忽略默认值?
答案 0 :(得分:9)
它不需要在那里。在运行时,JVM构造可以检索的注释实例。此实例将使用Child2
值进行初始化,该值位于注释本身的Child1
文件中。这表示为AnnotationDefault
attribute
Child2
属性是一个可变长度属性 某些dscmd3.Fill(dsS);
结构的属性表(§4.6),即 那些代表注释类型的元素。的default
属性记录由...表示的元素的默认值.class
结构。每个
AnnotationDefault
结构表示注释的元素 类型最多只能包含一个method_info
属性。 Java 虚拟机必须使此默认值可用,因此它可以 通过适当的反思API应用。
您最终将调用注释实例的AnnotationDefault
方法(或您定义的任何其他方法),它将返回该值。
答案 1 :(得分:4)
如果您查看注释的字节码,您将在那里看到默认值。使用'TestContorller', function($scope, $window)
并修剪不相关的内容:
$window.alert('action handler called')