Pytanie Czy jest możliwe odczytanie wartości adnotacji w java?


to jest mój kod:

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

czy można odczytać wartość mojej adnotacji @ Column (Nazwa kolumny= "xyz123") w innej klasie?


76
2017-11-28 13:16


pochodzenie




Odpowiedzi:


Tak, jeśli adnotacja w kolumnie zawiera rezerwę środowiska wykonawczego

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

możesz zrobić coś takiego

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



podoba mi się twoje rozwiązanie. W jaki sposób możemy uczynić go bardziej ogólnym, jak zamiast MyClass, chcę używać T jak dla (Field f: T.class.getFields ()) {column column = f.getAnnotation (Column.class); if (column! = null) System.out.println (column.columnName ()); } - ATHER
Dokładnie! Walczyłem też o to. Co się stanie, jeśli chcę mieć procesor adnotacji, który nie musi być jawnie opatrzony nazwą klasy? Czy można to zrobić, aby odebrać go z kontekstu; 'to'?? - 5122014009
Nie jestem pewien, czy rozumiem, czego potrzebujecie. Proszę zadać to jako nowe pytanie z pełnym przykładem. Możesz tutaj dodać link, jeśli chcesz. - Cephalopod
Posługiwać się Myclass.class.getDeclaredFields() aby uzyskać prywatne pola - q0re
To zadziałało dla mnie. dzięki. Szukałem prywatnych pól klasy superklasy, więc użyłem clsName.getSuperclass (). GetDeclaredFields () - Shashank


Oczywiście, że jest. Oto przykładowa adnotacja:

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

    String testText();
}

I przykładowa metoda z adnotacjami:

class TestClass {

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

I przykładowa metoda w innej klasie, która wypisuje wartość 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());
    }
}

Nie ma to większego znaczenia dla adnotacji w terenie, takich jak Twoja.

Cheerz!


67
2017-11-28 13:30



Wow bardzo fajnie! Dzięki za prosty przykład. Wyraźnie ilustruje proces krok po kroku. - Dan Torrey
Naprawdę dobre wyjaśnienie procesu pobierania wartości adnotacji. - Arlind


Nigdy tego nie robiłem, ale wygląda na to Odbicie zapewnia to. Field to jest AnnotatedElement i tak właśnie jest getAnnotation. Ta strona ma przykład (skopiowany poniżej); całkiem proste, jeśli znasz klasę adnotacji i czy polityka adnotacji zachowuje adnotację w czasie wykonywania. Oczywiście, jeśli zasady przechowywania nie zachowują adnotacji w czasie wykonywania, nie będzie można ich przesłać w czasie wykonywania.

Odpowiedź, która została usunięta (?), Stanowi przydatny link do samouczek adnotacji które mogą okazać się pomocne; Skopiowałem link, aby ludzie mogli z niego korzystać.

Przykład z ta strona:

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





Podczas gdy wszystkie dotychczasowe odpowiedzi są całkowicie poprawne, należy również pamiętać o biblioteka odbić google dla bardziej ogólnego i łatwego podejścia do skanowania adnotacji, np.

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

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

4
2018-02-05 08:34





Opracowując do odpowiedzi @ głowonoga, jeśli chciałbyś wszystkie nazwy kolumn na liście, możesz użyć tego 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());

3
2018-04-18 20:00



Objects.nonNull, aby w pełni objąć Java 8 :) .filter (f -> nonNull (f.getAnnotation (Column.class))) - dehumanizer


Możesz także użyć typów ogólnych, w moim przypadku, biorąc pod uwagę wszystko, co powiedziano, zanim będziesz mógł zrobić coś takiego:

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

    }

}

Pamiętaj, że to nie będzie w 100% równoważne do SomeClass.class.get (...) ();

Ale może załatwić sprawę ...


2
2018-05-12 16:51





W powszechnym przypadku masz prywatny dostęp do pól, więc NIE MOŻNA używać getFields w odbiciu. Zamiast tego powinieneś użyć getDeclaredFields

Tak więc, po pierwsze, powinieneś wiedzieć, czy adnotacja do kolumny ma zachowywanie w środowisku wykonawczym:

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

Potem możesz zrobić coś takiego:

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

Oczywiście, chciałbyś coś zrobić z polem - ustaw nową wartość za pomocą wartości adnotacji:

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

Tak więc pełny kod może wyglądać tak:

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