2011-08-29 9 views
8

Rozważmy następujący kod:Jak sprawdzić, czy parametr obecnej metody ma adnotację i pobrać tę wartość parametru w Javie?

public example(String s, int i, @Foo Bar bar) { 
    /* ... */ 
} 

Chcę sprawdzić, czy metoda ma adnotację @Foo i uzyskać argumentu lub wyjątek, jeśli nie @Foo adnotacja znajduje.

Moje obecne podejście jest, aby najpierw uzyskać aktualny sposób, a następnie iterację adnotacji parametrów:

import java.lang.annotation.Annotation; 
import java.lang.reflect.Method; 

class Util { 

    private Method getCurrentMethod() { 
     try { 
      final StackTraceElement[] stes = Thread.currentThread().getStackTrace(); 
      final StackTraceElement ste = stes[stes.length - 1]; 
      final String methodName = ste.getMethodName(); 
      final String className = ste.getClassName(); 
      final Class<?> currentClass = Class.forName(className); 
      return currentClass.getDeclaredMethod(methodName); 
     } catch (Exception cause) { 
      throw new UnsupportedOperationException(cause); 
     } 
    } 

    private Object getArgumentFromMethodWithAnnotation(Method method, Class<?> annotation) { 
     final Annotation[][] paramAnnotations = method.getParameterAnnotations();  
      for (Annotation[] annotations : paramAnnotations) { 
       for (Annotation an : annotations) { 
        /* ... */ 
       } 
      } 
    } 

} 

Czy to właściwe podejście, czy jest jakiś lepszy? Jak wyglądałby kod wewnątrz pętli forach? Nie jestem pewien, czy zrozumiałem, co faktycznie powraca getParameterAnnotations ...

+0

nie widzę nic złego masz już – skaffman

+0

+1 nie robi 'new Exception(). getStackTrace()' – Cephalopod

Odpowiedz

6

Zewnętrzna pętli

for (Annotation[] annotations : paramAnnotations) { 
    ... 
} 

powinien wykorzystać wyraźne licznik, w przeciwnym razie nie wiem, co parametr jesteś przetwarzanie teraz

final Annotation[][] paramAnnotations = method.getParameterAnnotations(); 
final Class[] paramTypes = method.getParameterTypes(); 
for (int i = 0; i < paramAnnotations.length; i++) { 
    for (Annotation a: paramAnnotations[i]) { 
     if (a instanceof Foo) { 
      System.out.println(String.format("parameter %d with type %s is annotated with @Foo", i, paramTypes[i]); 
     } 
    } 
} 

Również upewnić twój typ adnotacji jest opatrzone @Retention(RetentionPolicy.RUNTIME)

Z twojego pytania nie jest całkowicie jasne, co próbujesz zrobić. Zgadzamy się na różnicy parametrów formalnych vs rzeczywistych argumentów:

void foo(int x) { } 

{ foo(3); } 

gdzie x jest parametrem i 3 jest argument?

Nie można uzyskać argumentów metod za pomocą refleksji. Jeśli jest to w ogóle możliwe, musisz użyć pakietu sun.unsafe. Nie mogę ci o tym wiele powiedzieć.

+0

Tak, chcę uzyskać rzeczywisty argument, który jest opatrzony adnotacją '@ Foo'. – soc

+0

Powinieneś utworzyć jednoznaczne pytanie, które zostanie zgubione między (niepowiązanymi) materiałami do adnotacji. – Cephalopod

3

Jeśli szukasz adnotacji w tej metodzie, prawdopodobnie potrzebujesz method.getAnnotations() lub method.getDeclaredAnnotations().

Wywołanie method.getParameterAnnotations() daje adnotacje dotyczące formalnych parametrów metody, a nie samej metody.

Patrząc wstecz na tytuł pytania, podejrzewam, że to szukając adnotacji dotyczących parametrów, których nie przeczytałem w treści pytania. Jeśli tak jest, twój kod wygląda dobrze.

Zobacz Method Javadoc i AnnotatedElement Javadoc.

4

getParameterAnnotations zwraca tablicę o długości równej wartości parametrów metody. Każdy element w tej tablicy zawiera tablicę o wartości annotations dla tego parametru.
Tak więc getParameterAnnotations()[2][0] zawiera pierwszą ([0]) adnotację trzeciego parametru ([2]).

Jeśli trzeba tylko sprawdzić, czy co najmniej jeden parametr zawiera adnotację konkretnego typu, metoda mogłaby wyglądać następująco:

private boolean isAnyParameterAnnotated(Method method, Class<?> annotationType) { 
    final Annotation[][] paramAnnotations = method.getParameterAnnotations();  
    for (Annotation[] annotations : paramAnnotations) { 
     for (Annotation an : annotations) { 
      if(an.annotationType().equals(annotationType)) { 
       return true; 
      } 
     } 
    } 
    return false; 
} 
Powiązane problemy