Pregunta ¿Es posible leer el valor de una anotación en java?


este es mi código:

@Column(columnName="firstname")


private String firstName;

 @Column(columnName="lastname")
 private String lastName;

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

es posible leer el valor de mi anotación @Column (columnName= "xyz123") en otra clase?


76
2017-11-28 13:16


origen


Respuestas:


Sí, si su anotación de Columna tiene la retención de tiempo de ejecución

@Retention(RetentionPolicy.RUNTIME)
@interface Column {
    ....
}

puedes hacer algo como esto

for (Field f: MyClass.class.getFields()) {
   Column column = f.getAnnotation(Column.class);
   if (column != null)
       System.out.println(column.columnName());
}

90
2017-11-28 13:27



Por supuesto que es. Aquí hay una anotación de muestra:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {

    String testText();
}

Y un ejemplo de método anotado:

class TestClass {

    @TestAnnotation(testText="zyx")
    public void doSomething() {}
}

Y un método de muestra en otra clase que imprime el valor de testText:

Method[] methods = TestClass.class.getMethods();
for (Method m : methods) {
    if (m.isAnnotationPresent(TestAnnotation.class)) {
        TestAnnotation ta = m.getAnnotation(TestAnnotation.class);
        System.out.println(ta.testText());
    }
}

No es muy diferente para las anotaciones de campo como la tuya.

Cheerz!


67
2017-11-28 13:30



Nunca lo hice, pero parece Reflexión proporciona esto. Field es un AnnotatedElement y entonces tiene getAnnotation. Esta página tiene un ejemplo (copiado a continuación); bastante sencillo si conoce la clase de la anotación y si la política de anotación retiene la anotación en tiempo de ejecución. Naturalmente, si la política de retención no mantiene la anotación en tiempo de ejecución, no podrá consultarla en tiempo de ejecución.

Una respuesta que se ha eliminado desde entonces (?) Proporcionó un enlace útil para un tutorial de anotaciones que puede ser útil; Copié el enlace aquí para que la gente pueda usarlo.

Ejemplo de esta página:

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
  String str();

  int val();
}

class Meta {
  @MyAnno(str = "Two Parameters", val = 19)
  public static void myMeth(String str, int i) {
    Meta ob = new Meta();

    try {
      Class c = ob.getClass();

      Method m = c.getMethod("myMeth", String.class, int.class);

      MyAnno anno = m.getAnnotation(MyAnno.class);

      System.out.println(anno.str() + " " + anno.val());
    } catch (NoSuchMethodException exc) {
      System.out.println("Method Not Found.");
    }
  }

  public static void main(String args[]) {
    myMeth("test", 10);
  }
}

19
2017-11-28 13:23



Si bien todas las respuestas dadas hasta ahora son perfectamente válidas, también se debe tener en cuenta la biblioteca de reflexiones de google para un enfoque más genérico y fácil para el escaneo de anotaciones, p.

 Reflections reflections = new Reflections("my.project.prefix");

 Set<Field> ids = reflections.getFieldsAnnotatedWith(javax.persistence.Id.class);

4
2018-02-05 08:34



Atendiendo a la respuesta de @ Cefalópodo, si desea todos los nombres de columna en una lista, puede usar este delineador:

List<String> columns = 
        Arrays.asList(MyClass.class.getFields())
              .stream()
              .filter(f -> f.getAnnotation(Column.class)!=null)
              .map(f -> f.getAnnotation(Column.class).columnName())
              .collect(Collectors.toList());

3
2018-04-18 20:00



También puede usar tipos genéricos, en mi caso, teniendo en cuenta todo lo dicho antes de que pueda hacer algo como:

public class SomeTypeManager<T> {

    public SomeTypeManager(T someGeneric) {

        //That's how you can achieve all previously said, with generic types.
        Annotation[] an = someGeneric.getClass().getAnnotations();

    }

}

Recuerde que esto no equivaldrá al 100% de SomeClass.class.get (...) ();

Pero puede hacer el truco ...


2
2018-05-12 16:51



En caso común tienes privado acceso para los campos, por lo que NO PUEDE usar getFields en la reflexión En lugar de esto deberías usar getDeclaredFields

Entonces, en primer lugar, debe saber si su anotación de Columna tiene la retención en tiempo de ejecución:

@Retention(RetentionPolicy.RUNTIME)
@interface Column {
}

Después de eso, puedes hacer algo como esto:

for (Field f: MyClass.class.getDeclaredFields()) {
   Column column = f.getAnnotation(Column.class);
       // ...
}

Obviamente, le gustaría hacer algo con el campo: establezca un nuevo valor usando el valor de la anotación:

Column annotation = f.getAnnotation(Column.class);
if (annotation != null) {
    new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
        object,
        myCoolProcessing(
            annotation.value()
        )
    );
}

Entonces, el código completo se puede ver así:

for (Field f : MyClass.class.getDeclaredFields()) {
    Column annotation = f.getAnnotation(Column.class);
    if (annotation != null)
        new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
                object,
                myCoolProcessing(
                        annotation.value()
                )
        );
}

1
2017-10-19 07:12