Java'da bir ek açıklamanın değerini okumak mümkün müdür?


100

bu benim kodum:

@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 ek açıklamamın değerini ( columnName = "xyz123") başka bir sınıfta okumak mümkün mü?

Yanıtlar:


122

Evet, Sütun ek açıklamanız çalışma zamanı saklama özelliğine sahipse

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

bunun gibi bir şey yapabilirsin

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

GÜNCELLEME: Özel alanları kullanmak için

Myclass.class.getDeclaredFields()

1
çözümünü beğendim Sınıfım yerine nasıl daha genel hale getirebiliriz T'yi (Field f: T.class.getFields ()) {Column column = f.getAnnotation (Column.class); eğer (sütun! = boş) System.out.println (column.columnName ()); }
ATHER

1
Kesinlikle! Ben de bunu anlamaya çalışıyorum. Açıkça bir sınıf adıyla verilmesi gerekmeyen bir açıklama işlemcisine sahip olmak istersem ne olur? Bağlamdan almak için yapılabilir mi; 'bu'??
5122014009

İkinizin neye ihtiyacınız olduğunu anladığımdan emin değilim. Lütfen bunu eksiksiz bir örnekle yeni bir soru olarak sorun. Dilerseniz buraya bağlayabilirsiniz.
Cephalopod

3
Myclass.class.getDeclaredFields()Özel alanları almak için kullanın
2016

Benim için çalıştı. Teşekkürler. . Ben clsName.getSuperclass () kullanılan bu yüzden üst sınıf özel alanlar arıyordu getDeclaredFields ()
Shashank'ın

88

Tabiki öyle. İşte örnek bir ek açıklama:

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

    String testText();
}

Ve açıklamalı örnek bir yöntem:

class TestClass {

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

Ve başka bir sınıfta testText değerini yazdıran örnek bir yöntem:

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

Sizinki gibi alan açıklamaları için pek farklı değil.

Cheerz!


22

Bunu hiç yapmadım, ama görünüşe göre Reflection bunu sağlıyor. Fieldbir AnnotatedElementve öyle var getAnnotation. Bu sayfanın bir örneği var (aşağıda kopyalanmıştır); Ek açıklamanın sınıfını biliyorsanız ve açıklama ilkesi açıklamayı çalışma zamanında tutuyorsa oldukça basittir. Doğal olarak, saklama politikası ek açıklamayı çalışma zamanında tutmazsa, bunu çalışma zamanında sorgulayamazsınız.

O zamandan beri silinen bir cevap (?), Yararlı bulabileceğiniz bir ek açıklama öğreticisine faydalı bir bağlantı sağlamıştır ; İnsanların kullanabilmesi için bağlantıyı buraya kopyaladım.

Bu sayfadan örnek :

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'un cevabını detaylandırarak, bir listede tüm sütun adlarını istiyorsanız, bu oneliner'ı kullanabilirsiniz:

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 tamamen Java 8 :) .filter kucaklamak (f -> nonnull (f.getAnnotation (Column.class)))
dehumanizer

4

Şimdiye kadar verilen tüm cevaplar mükemmel şekilde geçerli olsa da, ek açıklama taramasına daha genel ve kolay bir yaklaşım için google yansımalar kitaplığı da akılda tutulmalıdır.

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

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

3

Benim durumumda, aşağıdaki gibi bir şey yapmadan önce söylenen her şeyi hesaba katarak genel türleri de kullanabilirsiniz:

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

    }

}

Unutmayın, bunun SomeClass.class.get (...) () 'e% 100 eşdeğer olmayacağını unutmayın;

Ama hile yapabilir ...


3

Genel bir durumda alanlar için özel erişiminiz vardır, bu nedenle yansımada getFields'ı KULLANAMAZSINIZ . Bunun yerine getDeclaredFields kullanmalısınız

Bu nedenle, ilk olarak, Sütun ek açıklamanızın çalışma zamanı saklama özelliğine sahip olup olmadığının farkında olmalısınız:

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

Bundan sonra şöyle bir şey yapabilirsiniz:

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

Açıkçası, alanla bir şeyler yapmak istiyorsunuz - ek açıklama değerini kullanarak yeni bir değer belirleyin:

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

Yani tam kod şöyle görünebilir:

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

Genel bir yöntem isteyen birkaç kişi için bu size yardımcı olacaktır (5 yıl sonra: p).

Aşağıdaki örneğim için, RequestMapping URL değerini RequestMapping ek açıklamasına sahip yöntemlerden alıyorum. Bunu alanlara uyarlamak için, sadece

for (Method method: clazz.getMethods())

-e

for (Field field: clazz.getFields())

Ve okumak istediğiniz ek açıklama için RequestMapping kullanımını değiştirin . Ancak ek açıklamada @Retention (RetentionPolicy.RUNTIME) olduğundan emin olun .

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

onu kullanma yollarından biri:

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;
}    
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.