Можно ли прочитать значение аннотации в java?

это мой код:

@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" ) в другом классе?

Ответ 1

Да, если у вашей аннотации 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()

Ответ 2

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

@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!

Ответ 3

Я никогда этого не делал, но это выглядит как Reflection. 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

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

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

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

Ответ 5

Разрабатывая ответ @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());

Ответ 6

В общем случае у вас есть закрытый доступ для полей, поэтому вы не можете использовать 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()
                )
        );
}

Ответ 7

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

public class SomeTypeManager<T> {

    public SomeTypeManager(T someGeneric) {

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

    }

}

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

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

Ответ 8

Тем немногим, кто просит универсальный метод, это должно помочь вам (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 "";
}