Чи можна прочитати значення примітки в java?


99

це мій код:

@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") в іншому класі?

Відповіді:


122

Так, якщо в анотації стовпця збережено час виконання

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

1
мені подобається ваше рішення. Як ми можемо зробити його більш загальним, як замість MyClass, я хочу використовувати T like for (поле f: T.class.getFields ()) {Column column = f.getAnnotation (Column.class); if (стовпець! = null) System.out.println (column.columnName ()); }
АТЕР

1
Саме так! Я теж намагаюся зрозуміти це. Що робити, якщо я хочу мати процесор анотацій, який не потребує прямого імені класу? Чи можна зробити так, щоб забрати його з контексту; 'це' ??
5122014009

Я не впевнений, що розумію, що вам потрібно двом. Будь ласка, поставте це як нове запитання з повним прикладом. Ви можете зв’язати його тут, якщо хочете.
Головоногі

3
Використовуйте Myclass.class.getDeclaredFields()для отримання приватних полів
q0re

Це працювало для мене. Дякую. . Я шукав суперкласу приватних полів , так що я використовував clsName.getSuperclass () getDeclaredFields ()
Shashank

88

Звичайно, так і є. Ось зразок примітки:

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

Не сильно відрізняється для анотацій на місцях, як ваша.

Боже!


21

Я ніколи цього не робив, але, схоже, це відображення забезпечує. 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);
  }
}

6

Розвиваючи відповідь @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());

Objects.nonNull повністю охопити Java 8 :) .filter (f -> nonNull (f.getAnnotation (Column.class)))
дегуманізатор

4

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

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

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

3

Ви також можете використовувати загальні типи, в моєму випадку, беручи до уваги все сказане, перш ніж ви можете зробити щось на кшталт:

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

Але можна зробити трюк ...


3

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

2

Для небагатьох людей, які запитують загальний метод, це повинно вам допомогти (через 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 "";
}

0

один із способів, яким я користувався:

protected List<Field> getFieldsWithJsonView(Class sourceClass, Class jsonViewName){
    List<Field> fields = new ArrayList<>();
    for (Field field : sourceClass.getDeclaredFields()) {
        JsonView jsonViewAnnotation = field.getDeclaredAnnotation(JsonView.class);
        if(jsonViewAnnotation!=null){
            boolean jsonViewPresent = false;
            Class[] viewNames = jsonViewAnnotation.value();
            if(jsonViewName!=null && Arrays.asList(viewNames).contains(jsonViewName) ){
                fields.add(field);
            }
        }
    }
    return fields;
}    
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.