जावा में आंतरिक रूप से @Override जैसे एनोटेशन कैसे काम करते हैं?


93

क्या कोई मुझे समझा सकता है कि एनोटेशन जावा में आंतरिक रूप से कैसे काम करते हैं?

मुझे पता है कि हम जावा में java.lang.annotation लाइब्रेरी का उपयोग करके कस्टम एनोटेशन कैसे बना सकते हैं। लेकिन मुझे अभी भी नहीं मिलता है कि यह आंतरिक रूप से कैसे काम कर रहा है उदाहरण के लिए, @Override एनोटेशन।

अगर मैं किसी को भी विस्तार से समझा सकता हूं तो मैं वास्तव में शुक्रगुजार हूं।


4
"आंतरिक रूप से काम करें" से आपका क्या मतलब है? संकलक? रनटाइम?
क्राय्लिस -कुट्टीओप्टिमिस्टिस्टिक-

3
@chrylis कार्य आंतरिक रूप से इसका अर्थ है कि यह कैसे पहचाना जाता है कि यह विधि ओवरराइड विधि है या यह ओवरराइड विधि नहीं है। यह दोनों समय पर काम है। जैसे संकलन समय में ओवरराइड एनोटेशन काम और वसंत नियंत्रक एनोटेशन रनटाइम में काम है
चिराग दासानी

जवाबों:


138

एनोटेशन के प्रकारों के बीच पहला मुख्य अंतर यह है कि क्या वे संकलन समय पर उपयोग किए जाते हैं और फिर उन्हें (जैसे @Override) त्याग दिया जाता है या संकलित क्लास फाइल में रखा जाता है और रनटाइम (जैसे स्प्रिंग @Component) पर उपलब्ध होता है । यह एनोटेशन की @Retention नीति द्वारा निर्धारित किया जाता है । यदि आप अपना एनोटेशन लिख रहे हैं, तो आपको यह तय करना होगा कि एनोटेशन रनटाइम के लिए सहायक है (ऑटोकैन्फिगेशन के लिए, शायद) या केवल संकलन समय (चेक या कोड जनरेशन के लिए)।

एनोटेशन के साथ कोड संकलित करते समय, कंपाइलर एनोटेशन को उसी तरह देखता है, जैसे कि वह सोर्स एलिमेंट्स पर अन्य मॉडिफायर देखता है, जैसे एक्सेस मॉडिफायर ( public/ private) या final। जब यह एक एनोटेशन का सामना करता है, तो यह एक एनोटेशन प्रोसेसर चलाता है, जो प्लग-इन क्लास की तरह है जो कहता है कि यह एक विशिष्ट एनोटेशन के लिए इच्छुक है। एनोटेशन प्रोसेसर आमतौर पर संकलित किए जा रहे तत्वों का निरीक्षण करने के लिए परावर्तन एपीआई का उपयोग करता है और बस उन पर चेक चला सकता है, उन्हें संशोधित कर सकता है या संकलित करने के लिए नया कोड उत्पन्न कर सकता है। @Overrideपहले का एक उदाहरण है; यह यह सुनिश्चित करने के लिए कि यह सुपरक्लॉस में से किसी एक में विधि हस्ताक्षर के लिए एक मैच पा सकता है और Messagerयह नहीं हो सकता है, तो संकलन त्रुटि का उपयोग करने के लिए रिफ्लेक्शन एपीआई का उपयोग करता है ।

एनोटेशन प्रोसेसर लिखने पर कई ट्यूटोरियल उपलब्ध हैं; यहाँ एक उपयोगी है । पर तरीकों के माध्यम से देखो इंटरफ़ेस कैसे संकलक एक एनोटेशन प्रोसेसर invokes के लिए; मुख्य ऑपरेशन विधि में होता है, जिसे हर बार कॉल करने वाले को एक तत्व दिखाई देता है जिसमें मिलान एनोटेशन होता है।Processorprocess


4
हमें यह बताना अच्छा लगेगा कि स्प्रिंग का एनोटेशन प्रोसेसर @ कॉमपोंन्ट को पार्स करता है और क्लास को उसके कंटेनर में इंजेक्ट करता है
जुन्चेन लियू

@shanyangqu इस सवाल के लिए ऑफ-टॉपिक है, जो स्प्रिंग-स्पेसिफिक नहीं है। आप स्वयं पोस्टप्रोसेसर कक्षाओं को पढ़ सकते हैं।
चेरिलिस -कुट्योपोटेमिमिस्टिक-

42

दूसरों ने जो सुझाव दिया है, इसके अलावा, मैं आपको एक एनोटेशन लिखने और उसके प्रोसेसर को स्क्रैच से देखने की सलाह देता हूं कि एनोटेशन कैसे काम करता है।

अपने आप में, उदाहरण के लिए, मैंने यह जांचने के लिए एक एनोटेशन लिखा है कि क्या संकलन समय में तरीके अतिभारित हैं।

सबसे पहले, नाम का एक एनोटेशन बनाएं Overload। इस एनोटेशन को विधि के लिए लागू किया जाता है इसलिए मैं इसके साथ एनोटेट करता हूं@Target(value=ElementType.METHOD)

package gearon.customAnnotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(value=ElementType.METHOD)
public @interface Overload {

}

अगला, परिभाषित एनोटेशन द्वारा एनोटेट किए गए तत्वों को संभालने के लिए संबंधित प्रोसेसर बनाएं। द्वारा एनोटेट की गई विधि के लिए @Overload, इसके हस्ताक्षर को एक से अधिक बार प्रदर्शित होना चाहिए। या त्रुटि छपी है।

package gearon.customAnnotation;

import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;

@SupportedAnnotationTypes("gearon.customAnnotation.Overload")

public class OverloadProcessor extends AbstractProcessor{

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        // TODO Auto-generated method stub
        HashMap<String, Integer> map = new HashMap<String, Integer>();

        for(Element element : roundEnv.getElementsAnnotatedWith(Overload.class)){
            String signature = element.getSimpleName().toString();
            int count = map.containsKey(signature) ? map.get(signature) : 0;
            map.put(signature, ++count);
        }

        for(Entry<String, Integer> entry: map.entrySet()){
            if(entry.getValue() == 1){
                processingEnv.getMessager().printMessage(Kind.ERROR, "The method which signature is " + entry.getKey() +  " has not been overloaded");
            }
        }
        return true;
    }
}

पैकेजिंग एनोटेशन और इसकी प्रक्रिया को जार फ़ाइल में रखने के बाद, @Overloadइसे संकलित करने के लिए javac.exe के साथ एक वर्ग बनाएं और उपयोग करें।

import gearon.customAnnotation.Overload;

public class OverloadTest {
    @Overload
    public static void foo(){
    }

    @Overload
    public static void foo(String s){

    }

    @Overload
    public static void nonOverloadedMethod(){

    }
} 

चूंकि nonOverloadedMethod()वास्तव में अतिभारित नहीं किया गया है, इसलिए हमें नीचे जैसा आउटपुट मिलेगा:

यहाँ छवि विवरण दर्ज करें


उपरोक्त जानकारी JDK6 (उस के लिए +1) के लिए बहुत अच्छा सम्मान है, लेकिन साथ ही साथ JDK5 का उपयोग करके समान चीज कैसे प्राप्त करें? JDK6 SupportedAnnotationTypes, AbstractProcessor class का उपयोग करना सरल हो गया लेकिन अतीत में ऐसा ही कैसे हुआ (jdk5 पर स्प्रिंग फ्रेमवर्क्स 2.5 की तरह)? कैसे JVM ने jdk5 में कक्षा के लिए एनोटेशन प्रोसेसर का पता लगाया? क्या आप 2 खंड (JDK5 के लिए एक, वर्तमान संस्करण Jdk6 + के लिए उत्तर) को संपादित करके मार्गदर्शन कर सकते हैं?
प्रजितगांधी

आपकी कक्षा में OverloadProcessor::processयह क्यों है entry.getValue() == 1? माता-पिता वर्ग / इंटरफ़ेस पर एक एनोटेशन जोड़ना नहीं है, इसलिए माता-पिता वर्ग / इंटरफ़ेस roundEnv.getElementsAnnotatedWith(Overload.class)नहीं मिलेगा, है ना?
बारिश हो रही

मैं इस हिस्से में उलझन में हूं लेकिन मुझे लगता है कि आपका जवाब बहुत मददगार है।
बारिश हो रही

@ s @e methodc̮͔̞ṛ̖̖e̬̣̦t̸͉̥̳̼ यदि किसी विधि को अधिभार के रूप में माना जाता है, तो कक्षा में समान नाम के साथ कम से कम दूसरी विधि होनी चाहिए।
यूजीन

1
@ ओवरलोडेड कहने की विधि के लिए, यह एक ही कक्षा में एक से अधिक बार दिखाई देना चाहिए, लेकिन यदि यह `== 1` है तो इसकी त्रुटि है।
कृष्णप्रभा

5

यहाँ है @Override: http://www.docjar.com/html/api/java/lang/Override.java.html

इसके बारे में कुछ विशेष नहीं है जो इसे एक एनोटेशन से अलग करता है जिसे आप स्वयं लिख सकते हैं। दिलचस्प बिट्स एनोटेशन के उपभोक्ताओं में हैं। जैसे एनोटेशन के लिए @Override, यह जावा कंपाइलर में ही होगा, या स्टैटिक कोड एनालिसिस टूल, या आपके आईडीई पर होगा।


1
मुझे पता है कि ओवरराइड एनोटेशन का स्रोत कोड। लेकिन यह आंतरिक रूप से कैसे काम करता है। जैसे कि यह कैसे पहचाना जा सकता है कि यह विधि ओवरराइड विधि नहीं है या यह एक ओवरराइड विधि है? या क्या मैं अपना कस्टम ओवरराइड एनोटेशन बना सकता हूं? और यह ठीक वैसा ही व्यवहार करना चाहिए जैसे जावा ओवरराइड एनोटेशन
चिराग दासानी

3
जैसा कि मैंने अपने जवाब में कहा, व्यवहार एनोटेशन का हिस्सा नहीं है। व्याख्या उन चीजों में निहित है जो एनोटेशन का उपभोग करते हैं। उसके कारण, जब तक आप उपभोक्ता को नहीं बदलते, आप व्यावहारिक रूप से अपना स्वयं का कस्टम संस्करण @Override(या अन्य मानक एनोटेशन) नहीं बना सकते ।
मैट बॉल

3

मूल रूप से, एनोटेशन केवल मार्कर होते हैं जिन्हें कंपाइलर या एप्लिकेशन द्वारा पढ़ा जाता है। उनकी अवधारण नीति के आधार पर वे केवल संकलन समय पर उपलब्ध हैं या प्रतिबिंब का उपयोग करके रनटाइम पर पठनीय हैं।

कई फ्रेमवर्क रनटाइम रिटेंशन का उपयोग करते हैं, अर्थात वे प्रतिबिंबित करते हैं कि क्या कुछ एनोटेशन एक वर्ग, विधि, क्षेत्र आदि पर मौजूद हैं और कुछ ऐसा करते हैं यदि एनोटेशन मौजूद है (या नहीं)। इसके अतिरिक्त, एनोटेशन के सदस्यों को आगे की जानकारी देने के लिए इस्तेमाल किया जा सकता है।


3

इस लिंक को फॉलो करें । यह आपकी समस्या के लिए करीबी जवाब प्रदान करेगा। यदि हम एनोटेशन पर ध्यान केंद्रित करते हैं Java, तो एनोटेशन जावा 5 में पेश किए गए थे और स्प्रिंग विशिष्ट नहीं हैं। सामान्य तौर पर, एनोटेशन आपको मेटाडेटा को क्लास, मेथड या वैरिएबल में जोड़ने की अनुमति देते हैं। एनोटेशन की व्याख्या कंपाइलर (उदाहरण के लिए, @ ऑवरराइड एनोटेशन) या स्प्रिंग जैसे फ्रेमवर्क द्वारा की जा सकती है (उदाहरण के लिए, @ कमेंट एनोटेशन)।

इसके अलावा मैं और संदर्भ जोड़ रहा हूं।

  1. http://www.codeproject.com/Articles/272736/Understanding-Annotations-in-Java
  2. http://docs.oracle.com/javase/7/docs/api/java/lang/annotation/package-summary.html
  3. http://www.coderanch.com/how-to/java/AnnotationsExample

@LuiggiMendoza जावा 1.7 एनोटेशन डॉक जोड़ा गया
रुचिरा गायन राणावेरा

@ रुचिरा मैं सभी लिंक खोली गई थी, लेकिन फिर भी मुझे यह साफ नहीं है कि यह कैसे काम करता है। क्या आप मुझे विवरण में समझा सकते हैं जैसे कि स्प्रिंग एनोटेशन पर विचार करें। मैं स्प्रिंग.xml फ़ाइल में किसी भी कॉन्फ़िगरेशन को लिखे बिना एनोटेशन का उपयोग करके सभी चीजें कर सकता हूं। क्या यह आंतरिक रूप से xml कॉन्फ़िगरेशन में एनोटेशन को बांधता है?
चिराग दासानी

@CiragDasani इस पर एक नज़र। यह आप में मदद मिल सकती static.springsource.org/spring/docs/3.0.0.M3/reference/html/... है और यह भी इस अतः पोस्ट देखें stackoverflow.com/questions/2798181/...
रुचिरा गायन Ranaweera

0

यहां तक ​​कि मैं भी उसी सवाल का जवाब ढूंढ रहा था। नीचे दिए गए लिंक ने एनोटेशन के अंदर लाने के लिए समेकित अच्छा सामान प्रदान किया। https://dzone.com/articles/how-annotations-work-java आशा है कि यह मदद करता है!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.