क्या जावा में एक एनोटेशन के मूल्य को पढ़ना संभव है?


98

यह मेरा कोड है:

@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 का उपयोग करना चाहता हूं (फ़ील्ड f: T.class.getFields ()) {कॉलम कॉलम = f.getAnnotation (कॉलम); if (कॉलम! = null) System.out.println (column.columnName ()); }
एटी

1
बिल्कुल सही! मैं यह पता लगाने के लिए संघर्ष कर रहा हूं कि बाहर भी। क्या होगा यदि मैं एक एनोटेशन प्रोसेसर रखना चाहता हूं जिसे स्पष्ट रूप से एक वर्ग नाम के साथ प्रदान करने की आवश्यकता नहीं है? क्या इसे संदर्भ से उठाया जा सकता है; 'यह'??
5122014009

मुझे यकीन नहीं है कि मुझे समझ में आया कि आप दोनों को क्या चाहिए। कृपया पूछें कि एक नए प्रश्न के रूप में एक पूर्ण उदाहरण के साथ। आप चाहें तो इसे यहां लिंक कर सकते हैं।
सेफालोपॉड

3
Myclass.class.getDeclaredFields()निजी क्षेत्रों को प्राप्त करने के लिए उपयोग करें
q0re

इसने मेरे लिए काम किया। धन्यवाद। मैं सुपरक्लास निजी क्षेत्रों की तलाश में था इसलिए मैंने clsName.getSuperclass () का उपयोग किया। getDeclaredFields ()
शशांक

88

निश्चित रूप से यह है। यहाँ एक नमूना एनोटेशन है:

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

    String testText();
}

और एक नमूना एनोटेट विधि:

class TestClass {

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

और एक अन्य वर्ग में एक नमूना विधि जो परीक्षण के मूल्य को प्रिंट करती है:

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!


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 के उत्तर के बारे में बताते हुए, यदि आप एक सूची में सभी स्तंभ नाम चाहते थे तो आप इस ऑनलाइनर का उपयोग कर सकते थे:

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 जावा 8 को पूरी तरह से गले लगाने के लिए :) .filter (f -> nonNull (f.getAnnotation (Column.class)))
dehumanizer

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 साल बाद: पी)।

मेरे नीचे के उदाहरण के लिए, मैं उन तरीकों से RequestMapping URL मान खींच रहा हूं जिनमें RequestMapping एनोटेशन है। खेतों के लिए इसे अनुकूलित करने के लिए, बस बदलना होगा

for (Method method: clazz.getMethods())

सेवा

for (Field field: clazz.getFields())

और आप जो भी एनोटेशन पढ़ना चाहते हैं , उसके लिए RequestMapping का स्वैप उपयोग । लेकिन यह सुनिश्चित करें कि एनोटेशन में @ रिटेंशन (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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.