Можно ли прочитать значение аннотации в Java? - PullRequest
89 голосов
/ 28 ноября 2010

это мой код:

@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;
 }

можно ли прочитать значение моей аннотации @Column ( columnName = "xyz123") в другом классе?

Ответы [ 8 ]

106 голосов
/ 28 ноября 2010

Да, если у вашей аннотации Column есть удержание времени выполнения

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

, вы можете сделать что-то вроде этого

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

ОБНОВЛЕНИЕ: Для получения приватных полей используйте

Myclass.class.getDeclaredFields()
78 голосов
/ 28 ноября 2010

Конечно, это так. Вот примерная аннотация:

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

    String testText();
}

И образец аннотированного метода:

class TestClass {

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

И пример метода в другом классе, который печатает значение 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());
    }
}

Не сильно отличается для полевых аннотаций, подобных вашей.

Cheerz!

19 голосов
/ 28 ноября 2010

Я никогда не делал этого, но похоже, что Отражение обеспечивает это. Field является AnnotatedElement и поэтому имеет getAnnotation. На этой странице есть пример (скопировано ниже); довольно просто, если вы знаете класс аннотации и если политика аннотации сохраняет аннотацию во время выполнения. Естественно, если политика хранения не сохраняет аннотацию во время выполнения, вы не сможете запросить ее во время выполнения.

Ответ, который с тех пор был удален (?), Содержит полезную ссылку на учебник по аннотациям , который может оказаться полезным; Я скопировал здесь ссылку, чтобы люди могли ее использовать.

Пример из этой страницы :

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);
  }
}
4 голосов
/ 18 апреля 2017

Развивая ответ @Cephalopod, если вам нужны все имена столбцов в списке, вы можете использовать этот oneliner:

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());
4 голосов
/ 05 февраля 2015

Несмотря на то, что все ответы, приведенные к настоящему моменту, абсолютно верны, следует также учитывать библиотеку google отражений для более общего и простого подхода к сканированию аннотаций, например

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

 Set<Field> ids = reflections.getFieldsAnnotatedWith(javax.persistence.Id.class);
3 голосов
/ 19 октября 2017

В общем случае у вас есть частный доступ к полям, поэтому вы НЕ МОЖЕТЕ использовать getFields в отражении.Вместо этого вы должны использовать getDeclaredFields

Итак, во-первых, вы должны знать, имеет ли ваша аннотация колонки время хранения:

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

После этого вы можете сделатьчто-то вроде этого:

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

Очевидно, вы хотели бы сделать что-то с полем - установите новое значение, используя значение аннотации:

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

Итак, полный код может выглядеть так:

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()
                )
        );
}
3 голосов
/ 12 мая 2016

Вы также можете использовать универсальные типы, в моем случае, с учетом всего сказанного, прежде чем вы сможете сделать что-то вроде:

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();

    }

}

Помните, что это не будет равно 100% SomeClass.class.get (...) ();

Но можно сделать трюк ...

1 голос
/ 05 февраля 2019

Для тех немногих, кто просит универсальный метод, это должно помочь вам (5 лет спустя: p).

В приведенном ниже примере я извлекаю значение URL-адреса RequestMapping из методов, имеющих аннотацию RequestMapping. Чтобы адаптировать это для полей, просто измените

for (Method method: clazz.getMethods())

до

for (Field field: clazz.getFields())

И поменяйте местами RequestMapping для любой аннотации, которую вы хотите прочитать. Но убедитесь, что аннотация имеет @ Retention (RetentionPolicy.RUNTIME) .

public static String getRequestMappingUrl(final Class<?> clazz, final String methodName)
{
    // Only continue if the method name is not empty.
    if ((methodName != null) && (methodName.trim().length() > 0))
    {
        RequestMapping tmpRequestMapping;
        String[] tmpValues;

        // Loop over all methods in the class.
        for (Method method: clazz.getMethods())
        {
            // If the current method name matches the expected method name, then keep going.
            if (methodName.equalsIgnoreCase(method.getName()))
            {
                // Try to extract the RequestMapping annotation from the current method.
                tmpRequestMapping = method.getAnnotation(RequestMapping.class);

                // Only continue if the current method has the RequestMapping annotation.
                if (tmpRequestMapping != null)
                {
                    // Extract the values from the RequestMapping annotation.
                    tmpValues = tmpRequestMapping.value();

                    // Only continue if there are values.
                    if ((tmpValues != null) && (tmpValues.length > 0))
                    {
                        // Return the 1st value.
                        return tmpValues[0];
                    }
                }
            }
        }
    }

    // Since no value was returned, log it and return an empty string.
    logger.error("Failed to find RequestMapping annotation value for method: " + methodName);

    return "";
}
...