2009-11-26 6 views
29

Wie kann ich den Wert einer Annotation für die annotierte Methode abrufen?Java-Annotationsattribut abrufen

ich habe:

@myAnnotation(attribute1 = value1, attibute2 = value2) 
public void myMethod() 
{ 
    //I want to get value1 here 
} 
+0

Können Sie weitere Details zu dem, was Sie erreichen möchten? – Carl

+0

Es ist nur wie ich sagte, ich möchte den Wert von Attribut1 verwenden, ohne es auf den Code –

+0

zu wiederholen, das ist nicht wirklich eine effektive Programmiermethode. Es hat hier keinen Vorteil, die Werte in einer Annotation zu setzen, anstatt sie in endgültigen Variablen innerhalb des Codes zu setzen oder sie in endgültigen statischen Variablen außerhalb der Methode zu setzen. – Jherico

Antwort

43
  1. Method Instanz erhalten.
  2. Annotation abrufen.
  3. Erhalten Sie den Anmerkungsattributwert.

Etwas wie:

Method m = getClass().getMethod("myMethod"); 
MyAnnotation a = m.getAnnotation(MyAnnotation.class); 
MyValueType value1 = a.attribute1(); 

Hier finden Sie die entsprechenden Ausnahmen, natürlich fangen müssen/handhaben. Die oben vorausgesetzt, dass Sie sind in der Tat Methode aus der aktuellen Klasse Abrufen (ersetzen getClass() mit Class.forName() sonst), und das Verfahren in Frage ist öffentlich (Verwendung getDeclaredMethods() wenn das nicht der Fall ist)

+0

sollte es nicht sein "MyValueType value1 = a.getAttribute1();" –

+0

oder mehr wie "a.attribute()' – Bozho

+0

Sicher sollte. Vielen Dank, bearbeitet – ChssPly76

19

Zwei wichtige Dinge:

  • Es ist keine Möglichkeit, die aktuelle Methode, z Es gibt keine getMethod() wie getClass(). Daher muss die Methode, die auf ihre eigene Annotation zugreift, ihren eigenen Namen kennen.
  • Die Aufbewahrungsrichtlinie der Annotation muss auf RUNTIME festgelegt sein, damit Sie während der Laufzeit auf die Annotation zugreifen können. Der Standardwert ist die Kompilierungszeit. Dies bedeutet, dass Annotationen in der Klassendatei verfügbar sind, aber nicht zur Laufzeit über Reflektion zugegriffen werden kann.

Voll Beispiel:

@Retention(RetentionPolicy.RUNTIME) 
public static @interface MyAnnotation { 
    String value1(); 

    int value2(); 
} 

@Test 
@MyAnnotation(value1 = "Foo", value2 = 1337) 
public void testAnnotation() throws Exception { 
    Method[] methods = getClass().getMethods(); 
    Method method = methods[0]; 
    assertEquals("testAnnotation", method.getName()); 
    MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); 
    assertEquals("Foo", annotation.value1()); 
    assertEquals(1337, annotation.value2()); 
} 
+4

Es gibt eine Möglichkeit, die aktuelle Methode zu erhalten. Entweder 'Thread.currentThread(). getStackTrace() [2] .getMethodName() 'oder' new Throwable(). FillInStackTrace(). GetStackTrace() [0].getMethodName() 'sollte es tun. – ChssPly76

+1

+1 für die Erwähnung der Retention – basszero

+1

@ ChssPly76, ist das Erstellen eines Stacktrace nicht ganz zuverlässig, wie die Javadocs erwähnen: "Einige virtuelle Maschinen können unter Umständen einen oder mehrere Stackframes aus dem Stacktrace auslassen. Im Extremfall Eine virtuelle Maschine, die keine Stack-Trace-Informationen [...] besitzt, darf von dieser Methode ein Array mit einer Länge von Null zurückgeben. " – gustafc

1

@mhaller: ein bisschen zu lang für einen Kommentar zu Ihrem Beitrag. Offensichtlich müssten weitere Verfeinerung mit überladenen Methoden zu behandeln, aber es ist nicht unmöglich .:

import java.lang.reflect.Method; 

public class Hack { 
    public static void main (String[] args) { 
     (new Hack()).foobar(); 
    } 
    public void foobar() { 
     Method here = getCurrentMethod(this); 
     System.out.format("And here we are: %s\n", here); 
    } 
    public static final Method getCurrentMethod(Object o) { 
     String s = Thread.currentThread().getStackTrace()[2].getMethodName(); 
     Method cm = null; 
     for(Method m : o.getClass().getMethods()){ 
      if(m.getName().equals(s)){ 
       cm = m; break; 
      } 
     } 
     return cm; 
    } 
} 

[edit: Kredit/dank Alexandr Priymak für das Auffinden des Fehlers in main()]

+3

Ich habe das Gefühl, dass wenn Sie dies tatsächlich im Produktionscode tun, ruft es die Großen Alten herbei, um Ihre Seele zu verschlingen! –

+0

@Skip Head - warum? Es gibt zwei Dinge, die hier zu beachten sind: (1) Array-Index ** in der Theorie ** kann von 2 auf einigen JVMs abweichen, aber das ist einfach zu umgehen, wenn man durch die ganze Spur läuft; (2) Dies funktioniert nicht für überladene Methoden; Sie können mit javassist etwas schwarze Magie machen, um die richtige zu erraten, die auf der Zeilennummer basiert, aber das ist wirklich etwas zweifelhaft. Abgesehen davon funktioniert es perfekt - wie denken Sie, dass Stack-Traces funktionieren? – ChssPly76

+0

@ ChssPly76: Keine Notwendigkeit, die ganze Spur zu gehen. Die Trace-Methode beginnt oben und läuft, bis sie sich selbst findet. Und der Anrufer ist der nächste. – alphazero

0

Um die Aktuelle Methode, versuchen Sie es mit diesem Code:

Thread.currentThread().getStackTrace()[1].getClassName().toString()+\".\"+Thread.currentThread().getStackTrace()[1].getMethodName().toString()