2011-08-29 15 views
8

consideran este código:¿Cómo comprobar si un parámetro del método actual tiene una anotación y recuperar ese valor del parámetro en Java?

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

Quiero comprobar si el método tiene una anotación @Foo y obtener el argumento o una excepción si no se encuentra ninguna @Foo anotación.

Mi enfoque actual es conseguir primero el método actual y luego iterar a través de las anotaciones de los parámetros:

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) { 
        /* ... */ 
       } 
      } 
    } 

} 

Es este el enfoque correcto o hay una mejor? ¿Cómo se vería el código dentro del lazo del forjado? No estoy seguro de haber entendido lo que realmente devuelve getParameterAnnotations ...

+0

no veo nada de malo en que ya tiene – skaffman

+0

1 por no hacer 'new Exception(). getStackTrace()' – Cephalopod

Respuesta

6

El ciclo for exterior

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

debe utilizar un contador explícita, de lo contrario no sabe qué parámetro se está procesando en este momento

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]); 
     } 
    } 
} 

También asegúrese de que su tipo de anotación se anota con @Retention(RetentionPolicy.RUNTIME)

De su pregunta no está del todo claro lo que está tratando de hacer. Estamos de acuerdo en la diferencia de los parámetros formales vs. argumentos reales:

void foo(int x) { } 

{ foo(3); } 

donde x es un parámetro y 3 es un argumento?

No es posible obtener los argumentos de los métodos a través de la reflexión. Si es posible, deberá usar el paquete sun.unsafe. Sin embargo, no puedo decirte mucho sobre eso.

+0

Sí, quiero obtener el argumento real que está anotado con '@ Foo'. – soc

+0

Debe crear una pregunta explícita para eso, ya que se pierde entre las cosas de anotación (no relacionadas). – Cephalopod

3

Si está buscando anotaciones sobre el método, probablemente quiera method.getAnnotations() o method.getDeclaredAnnotations().

La llamada method.getParameterAnnotations() le da anotaciones sobre los parámetros formales del método, no sobre el método en sí.

Mirando hacia atrás en el título de la pregunta, sospecho que están buscando anotaciones en los parámetros, que no leí en el contenido de la pregunta. Si ese es el caso, tu código se ve bien.

Ver Method Javadoc y AnnotatedElement Javadoc.

4

getParameterAnnotations devuelve una matriz con la longitud igual a la cantidad de parámetros del método. Cada elemento en esa matriz contiene una matriz de annotations en ese parámetro.
Por lo tanto, getParameterAnnotations()[2][0] contiene la primera anotación ([0]) del tercer parámetro ([2]).

Si sólo necesita comprobar si al menos un parámetro contiene una anotación de un tipo específico, el método podría tener este aspecto:

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; 
} 
Cuestiones relacionadas