Provo ad implementare diverse analisi statiche per bytecode Java. Cercano di calcolare se un determinato metodo ha una proprietà specifica, ad es. è un metodo di fabbrica. Poiché queste analisi sono difficili da testare, ho deciso di scrivere del codice Java e di annotare i metodi direttamente con la proprietà corretta. Dopo aver eseguito l'analisi, è abbastanza semplice controllare automaticamente se la proprietà calcolata e quella annotata è la stessa.I valori predefiniti dell'annotazione Java vengono compilati in bytecode?
MyAnnotation:
@Retention(RUNTIME)
@Target(METHOD)
public @interface FactoryMethodProperty {
FactoryMethodKeys value() default FactoryMethodKeys.NonFactoryMethod;
}
codice di prova Esempio:
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();
}
}
Poiché la maggior parte dei metodi nel mio codice di prova sono metodi di fabbrica, ho impostato il valore di default per il valore enum "FactoryMethodKeys.NonFactoryMethod ". Ma quando non passo esplicitamente il valore enum all'annotazione, non viene compilato nel bytecode.
Bytecode:
#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
}
cosa ho sbagliato? Perché il valore predefinito è completamente ignorato?