Java Language
एनोटेशन
खोज…
परिचय
जावा में, एक एनोटेशन सिंटैक्टिक मेटाडेटा का एक रूप है जिसे जावा स्रोत कोड में जोड़ा जा सकता है। यह एक ऐसे प्रोग्राम के बारे में डेटा प्रदान करता है जो प्रोग्राम का हिस्सा नहीं है। एनोटेशन का उस कोड के संचालन पर कोई सीधा प्रभाव नहीं पड़ता है जो वे एनोटेट करते हैं। कक्षाओं, विधियों, चर, मापदंडों और संकुल को एनोटेट करने की अनुमति है।
वाक्य - विन्यास
- @AnnotationName // 'मार्कर एनोटेशन' (कोई पैरामीटर नहीं)
- @AnnotationName (someValue) // 'मान' नाम के साथ पैरामीटर सेट करता है
- @AnnotationName (param1 = value1) // नामित पैरामीटर
- @AnnotationName (param1 = value1, param2 = value2) // कई नामित पैरामीटर
- @AnnotationName (param1 = {1, 2, 3}) // नाम सरणी पैरामीटर
- @AnnotationName ({value1}) // एकल तत्व के साथ सरणी जिसका मान 'नाम' के पैरामीटर के साथ है
टिप्पणियों
पैरामीटर प्रकार
केवल निम्न प्रकार के निरंतर भावों को पैरामीटर के लिए अनुमति दी जाती है, साथ ही इन प्रकारों के सरणियों:
-
String
-
Class
- आदिम प्रकार
- Enum प्रकार
- एनोटेशन प्रकार
बिल्ट-इन एनोटेशन
जावा का मानक संस्करण पूर्वनिर्धारित कुछ एनोटेशन के साथ आता है। आपको उन्हें खुद से परिभाषित करने की आवश्यकता नहीं है और आप उन्हें तुरंत उपयोग कर सकते हैं। वे संकलक को कुछ मौलिक तरीकों, कक्षाओं और कोड की जाँच करने में सक्षम बनाते हैं।
@Override
यह एनोटेशन एक विधि पर लागू होता है और कहता है कि इस विधि को सुपरक्लास की विधि को ओवरराइड करना चाहिए या अमूर्त सुपरक्लास की विधि की परिभाषा को लागू करना चाहिए। यदि इस एनोटेशन का उपयोग किसी अन्य प्रकार की विधि के साथ किया जाता है, तो संकलक एक त्रुटि फेंक देगा।
ठोस सुपरक्लास
public class Vehicle {
public void drive() {
System.out.println("I am driving");
}
}
class Car extends Vehicle {
// Fine
@Override
public void drive() {
System.out.prinln("Brrrm, brrm");
}
}
सार वर्ग
abstract class Animal {
public abstract void makeNoise();
}
class Dog extends Animal {
// Fine
@Override
public void makeNoise() {
System.out.prinln("Woof");
}
}
काम नहीं करता
class Logger1 {
public void log(String logString) {
System.out.prinln(logString);
}
}
class Logger2 {
// This will throw compile-time error. Logger2 is not a subclass of Logger1.
// log method is not overriding anything
@Override
public void log(String logString) {
System.out.println("Log 2" + logString);
}
}
मुख्य उद्देश्य गलत तरीके से पकड़ना है, जहां आपको लगता है कि आप एक विधि से आगे निकल रहे हैं, लेकिन वास्तव में एक नए को परिभाषित कर रहे हैं।
class Vehicle {
public void drive() {
System.out.println("I am driving");
}
}
class Car extends Vehicle {
// Compiler error. "dirve" is not the correct method name to override.
@Override
public void dirve() {
System.out.prinln("Brrrm, brrm");
}
}
ध्यान दें कि @Override
का अर्थ समय के साथ बदल गया है:
- जावा 5 में, इसका मतलब था कि एनोटेट विधि को सुपरक्लास श्रृंखला में घोषित गैर-सार पद्धति को ओवरराइड करना था।
- जावा 6 आगे से, यह भी संतुष्ट है कि यदि एनोटेट पद्धति कक्षाओं सुपरक्लास / इंटरफ़ेस पदानुक्रम में घोषित एक सार पद्धति को लागू करती है।
(यह कभी-कभी समस्याओं का कारण बन सकता है जब जावा 5 में बैक-पोर्टिंग कोड हो)
@Deprecated
यह विधि को पदावनत के रूप में चिह्नित करता है। इसके कई कारण हो सकते हैं:
एपीआई त्रुटिपूर्ण है और ठीक करने के लिए अव्यावहारिक है,
एपीआई के उपयोग से त्रुटियों की संभावना है,
एपीआई को दूसरे एपीआई द्वारा अधिगृहीत किया गया है,
एपीआई अप्रचलित है,
एपीआई प्रयोगात्मक है और असंगत परिवर्तनों के अधीन है,
या ऊपर के किसी भी संयोजन।
अपव्यय का विशिष्ट कारण आमतौर पर एपीआई के दस्तावेज में पाया जा सकता है।
एनोटेशन संकलक को त्रुटि का कारण बना देगा यदि आप इसका उपयोग करते हैं। आईडीई भी इस विधि को किसी भी तरह से हटा सकते हैं
class ComplexAlgorithm {
@Deprecated
public void oldSlowUnthreadSafeMethod() {
// stuff here
}
public void quickThreadSafeMethod() {
// client code should use this instead
}
}
@चेतावनियों को दबाना
लगभग सभी मामलों में, जब संकलक एक चेतावनी का उत्सर्जन करता है, तो सबसे उपयुक्त कार्रवाई कारण को ठीक करना है। कुछ उदाहरणों में (उदाहरण के लिए, अप्रचलित-सुरक्षित प्री-जेनरिक कोड का उपयोग करके जेनरिक कोड) यह संभव नहीं हो सकता है और उन चेतावनियों को दबाने से बेहतर है कि आप अपेक्षा करते हैं और ठीक नहीं कर सकते हैं, इसलिए आप अधिक स्पष्ट रूप से अप्रत्याशित चेतावनी देख सकते हैं।
इस एनोटेशन को पूरी कक्षा, विधि या लाइन पर लागू किया जा सकता है। यह पैरामीटर के रूप में चेतावनी की श्रेणी लेता है।
@SuppressWarnings("deprecation")
public class RiddledWithWarnings {
// several methods calling deprecated code here
}
@SuppressWarning("finally")
public boolean checkData() {
// method calling return from within finally block
}
जितना संभव हो सके एनोटेशन के दायरे को सीमित करना बेहतर है, ताकि अप्रत्याशित चेतावनियों को भी दबाया जा सके। उदाहरण के लिए, एनोटेशन के दायरे को सिंगल-लाइन तक सीमित करना:
ComplexAlgorithm algorithm = new ComplexAlgorithm();
@SuppressWarnings("deprecation") algoritm.slowUnthreadSafeMethod();
// we marked this method deprecated in an example above
@SuppressWarnings("unsafe") List<Integer> list = getUntypeSafeList();
// old library returns, non-generic List containing only integers
इस एनोटेशन द्वारा समर्थित चेतावनी संकलक से संकलक तक भिन्न हो सकती है। केवल unchecked
और deprecation
चेतावनी विशेष रूप से जेएलएस में उल्लिखित है। गैर-मान्यता प्राप्त चेतावनी प्रकारों की अनदेखी की जाएगी।
@SafeVarargs
प्रकार के क्षरण के कारण, void method(T... t)
को void method(Object[] t)
परिवर्तित किया जाएगा, जिसका अर्थ है कि कंपाइलर हमेशा यह सत्यापित करने में सक्षम नहीं है कि वेरिएग का उपयोग टाइप-सुरक्षित है। उदाहरण के लिए:
private static <T> void generatesVarargsWarning(T... lists) {
ऐसे उदाहरण हैं जहां उपयोग सुरक्षित है, जिस स्थिति में आप चेतावनी को दबाने के लिए SafeVarargs
एनोटेशन के साथ विधि को एनोटेट कर सकते हैं। यह स्पष्ट रूप से चेतावनी को छुपाता है यदि आपका उपयोग असुरक्षित भी है।
@FunctionalInterface
यह एक वैकल्पिक एनोटेशन है जिसका उपयोग फंक्शनलइंटरफेस को चिह्नित करने के लिए किया जाता है। यह संकलक को शिकायत करेगा कि क्या यह फंक्शनलइंटरफेस अटकल के अनुरूप नहीं है (एक अमूर्त विधि है)
@FunctionalInterface
public interface ITrade {
public boolean check(Trade t);
}
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
प्रतिबिंब के माध्यम से रनटाइम एनोटेशन की जाँच करता है
जावा का परावर्तन एपीआई प्रोग्रामर को रनटाइम के दौरान क्लास फ़ील्ड, विधियों और एनोटेशन पर विभिन्न जांच और संचालन करने की अनुमति देता है। हालांकि, एक टिप्पणी के क्रम में सभी दृश्य पर होने के लिए आदेश में, RetentionPolicy
लिए परिवर्तित किया जाना चाहिए RUNTIME
, के रूप में नीचे दिए गए उदाहरण में प्रदर्शन किया:
@interface MyDefaultAnnotation {
}
@Retention(RetentionPolicy.RUNTIME)
@interface MyRuntimeVisibleAnnotation {
}
public class AnnotationAtRuntimeTest {
@MyDefaultAnnotation
static class RuntimeCheck1 {
}
@MyRuntimeVisibleAnnotation
static class RuntimeCheck2 {
}
public static void main(String[] args) {
Annotation[] annotationsByType = RuntimeCheck1.class.getAnnotations();
Annotation[] annotationsByType2 = RuntimeCheck2.class.getAnnotations();
System.out.println("default retention: " + Arrays.toString(annotationsByType));
System.out.println("runtime retention: " + Arrays.toString(annotationsByType2));
}
}
एनोटेशन प्रकारों को परिभाषित करना
एनोटेशन प्रकार @interface
साथ परिभाषित किए @interface
। पैरामीटर को एक नियमित इंटरफ़ेस के तरीकों के समान परिभाषित किया गया है।
@interface MyAnnotation {
String param1();
boolean param2();
int[] param3(); // array parameter
}
डिफ़ॉल्ट मान
@interface MyAnnotation {
String param1() default "someValue";
boolean param2() default true;
int[] param3() default {};
}
मेटा-एनोटेशन
मेटा-एनोटेशन एनोटेशन हैं जिन्हें एनोटेशन प्रकारों पर लागू किया जा सकता है। विशेष पूर्वनिर्धारित मेटा-एनोटेशन परिभाषित करते हैं कि एनोटेशन प्रकार का उपयोग कैसे किया जा सकता है।
@Target
@Target
मेटा-एनोटेशन उन @Target
प्रतिबंधित करता है जिन पर एनोटेशन लागू किया जा सकता है।
@Target(ElementType.METHOD)
@interface MyAnnotation {
// this annotation can only be applied to methods
}
सरणी संकेतन का उपयोग करके कई मान जोड़े जा सकते हैं, जैसे @Target({ElementType.FIELD, ElementType.TYPE})
उपलब्ध मान
elementType | लक्ष्य | उदाहरण लक्ष्य तत्व पर उपयोग |
---|---|---|
ANNOTATION_TYPE | एनोटेशन प्रकार | |
निर्माता | कंस्ट्रक्टर्स | |
खेत | क्षेत्र, एनम स्थिरांक | |
LOCAL_VARIABLE | तरीकों के अंदर परिवर्तन की घोषणा | |
पैकेज | पैकेज ( package-info.java ) | |
तरीका | तरीकों | |
पैरामीटर | विधि / निर्माण मापदंडों | |
प्रकार | कक्षाएं, इंटरफेस, एनम | |
elementType | लक्ष्य | उदाहरण लक्ष्य तत्व पर उपयोग |
---|---|---|
TYPE_PARAMETER | टाइप पैरामीटर घोषणाएं | |
TYPE_USE | एक प्रकार का उपयोग | |
@Retention
@Retention
मेटा-एनोटेशन एप्लिकेशन संकलन प्रक्रिया या निष्पादन के दौरान एनोटेशन दृश्यता को परिभाषित करता है। डिफ़ॉल्ट रूप से, एनोटेशन .class
फ़ाइलों में शामिल होते हैं, लेकिन रनटाइम पर दिखाई नहीं देते हैं। किसी एनोटेशन को रनटाइम पर पहुँच योग्य बनाने के लिए, उस एनोटेशन पर RetentionPolicy.RUNTIME
सेट करना होगा।
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
// this annotation can be accessed with reflections at runtime
}
उपलब्ध मूल्य
अवधारण नीति | प्रभाव |
---|---|
कक्षा | एनोटेशन .class फ़ाइल में उपलब्ध है, लेकिन रनटाइम पर नहीं |
क्रम | एनोटेशन रनटाइम पर उपलब्ध है और प्रतिबिंब के माध्यम से पहुँचा जा सकता है |
स्रोत | एनोटेशन संकलन समय पर उपलब्ध है, लेकिन .class फ़ाइलों में नहीं जोड़ा गया है। एनोटेशन का उपयोग एनोटेशन प्रोसेसर द्वारा किया जा सकता है। |
@Documented
@Documented
मेटा-एनोटेशन का उपयोग एनोटेशन को चिह्नित करने के लिए किया जाता है जिसका उपयोग एपीआई प्रलेखन जनरेटर द्वारा javadoc की तरह किया जाना चाहिए। इसका कोई मूल्य नहीं है। @Documented
साथ, एनोटेशन का उपयोग करने वाले सभी वर्ग इसे अपने उत्पन्न प्रलेखन पृष्ठ पर सूचीबद्ध करेंगे। @Documented
बिना, यह देखना संभव नहीं है कि कौन से वर्ग प्रलेखन में एनोटेशन का उपयोग करते हैं।
@Inherited
@Inherited
मेटा-एनोटेशन उन एनोटेशन के लिए प्रासंगिक है जो कक्षाओं में लागू होते हैं। इसका कोई मूल्य नहीं है। एनोटेशन को @Inherited
रूप में चिह्नित करना उस तरीके को बदल देता है जिससे एनोटेशन क्वेरी काम करती है।
- एक गैर-विरासत वाले एनोटेशन के लिए, क्वेरी केवल उस वर्ग की जांच करती है जिसकी जांच की जा रही है।
- विरासत में दिए गए एनोटेशन के लिए, क्वेरी तब तक सुपर-क्लास चेन (पुनरावर्ती) की जांच करेगी जब तक एनोटेशन का एक उदाहरण नहीं मिलता है।
ध्यान दें कि केवल सुपर-कक्षाओं को ही उद्धृत किया जाता है: कक्षाओं के पदानुक्रम में इंटरफेस से जुड़े किसी भी एनोटेशन को अनदेखा किया जाएगा।
@Repeatable
जावा में @Repeatable
मेटा-एनोटेशन जोड़ा गया था। यह इंगित करता है कि एनोटेशन के कई उदाहरण एनोटेशन के लक्ष्य से जुड़े हो सकते हैं। इस मेटा-एनोटेशन का कोई मूल्य नहीं है।
रन-टाइम पर एनोटेशन मान प्राप्त करना
आप विधि या फ़ील्ड या वर्ग लाने के लिए परावर्तन का उपयोग करके एनोटेशन के वर्तमान गुणों को प्राप्त कर सकते हैं, जिस पर एनोटेशन लागू होता है, और फिर वांछित गुणों को प्राप्त करना।
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String key() default "foo";
String value() default "bar";
}
class AnnotationExample {
// Put the Annotation on the method, but leave the defaults
@MyAnnotation
public void testDefaults() throws Exception {
// Using reflection, get the public method "testDefaults", which is this method with no args
Method method = AnnotationExample.class.getMethod("testDefaults", null);
// Fetch the Annotation that is of type MyAnnotation from the Method
MyAnnotation annotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);
// Print out the settings of the Annotation
print(annotation);
}
//Put the Annotation on the method, but override the settings
@MyAnnotation(key="baz", value="buzz")
public void testValues() throws Exception {
// Using reflection, get the public method "testValues", which is this method with no args
Method method = AnnotationExample.class.getMethod("testValues", null);
// Fetch the Annotation that is of type MyAnnotation from the Method
MyAnnotation annotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);
// Print out the settings of the Annotation
print(annotation);
}
public void print(MyAnnotation annotation) {
// Fetch the MyAnnotation 'key' & 'value' properties, and print them out
System.out.println(annotation.key() + " = " + annotation.value());
}
public static void main(String[] args) {
AnnotationExample example = new AnnotationExample();
try {
example.testDefaults();
example.testValues();
} catch( Exception e ) {
// Shouldn't throw any Exceptions
System.err.println("Exception [" + e.getClass().getName() + "] - " + e.getMessage());
e.printStackTrace(System.err);
}
}
}
आउटपुट होगा
foo = bar
baz = buzz
बार-बार एनोटेशन
जावा 8 तक, एक ही एनोटेशन के दो उदाहरणों को एक तत्व पर लागू नहीं किया जा सकता है। मानक वर्कअराउंड का उपयोग कुछ अन्य एनोटेशन के एक सरणी रखने वाले कंटेनर एनोटेशन का उपयोग करने के लिए किया गया था:
// Author.java
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
String value();
}
// Authors.java
@Retention(RetentionPolicy.RUNTIME)
public @interface Authors {
Author[] value();
}
// Test.java
@Authors({
@Author("Mary"),
@Author("Sam")
})
public class Test {
public static void main(String[] args) {
Author[] authors = Test.class.getAnnotation(Authors.class).value();
for (Author author : authors) {
System.out.println(author.value());
// Output:
// Mary
// Sam
}
}
}
जावा 8, कंटेनर एनोटेशन का उपयोग करने के लिए एक स्वच्छ, अधिक पारदर्शी तरीका प्रदान करता है, @Repeatable
एनोटेशन का उपयोग करके। पहले हम इसे Author
वर्ग में जोड़ते हैं:
@Repeatable(Authors.class)
यह जावा को कई @Author
एनोटेशन का इलाज करने के लिए कहता है, क्योंकि वे @Authors
कंटेनर से घिरे थे। हम अपने कंटेनर के बजाय, अपने वर्ग द्वारा @Author
सरणी तक पहुंचने के लिए Class.getAnnotationsByType()
का भी उपयोग कर सकते हैं:
@Author("Mary")
@Author("Sam")
public class Test {
public static void main(String[] args) {
Author[] authors = Test.class.getAnnotationsByType(Author.class);
for (Author author : authors) {
System.out.println(author.value());
// Output:
// Mary
// Sam
}
}
}
निहित एनोटेशन
डिफ़ॉल्ट वर्ग एनोटेशन पर उन्हें बढ़ाने के प्रकारों पर लागू नहीं होता है। इसे एनोटेशन परिभाषा में @Inherited
एनोटेशन जोड़कर बदला जा सकता है
उदाहरण
निम्नलिखित 2 टिप्पणियों पर विचार करें:
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedAnnotationType {
}
तथा
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface UninheritedAnnotationType {
}
यदि तीन वर्गों को इस तरह एनोटेट किया जाता है:
@UninheritedAnnotationType
class A {
}
@InheritedAnnotationType
class B extends A {
}
class C extends B {
}
इस कोड को चला रहा है
System.out.println(new A().getClass().getAnnotation(InheritedAnnotationType.class));
System.out.println(new B().getClass().getAnnotation(InheritedAnnotationType.class));
System.out.println(new C().getClass().getAnnotation(InheritedAnnotationType.class));
System.out.println("_________________________________");
System.out.println(new A().getClass().getAnnotation(UninheritedAnnotationType.class));
System.out.println(new B().getClass().getAnnotation(UninheritedAnnotationType.class));
System.out.println(new C().getClass().getAnnotation(UninheritedAnnotationType.class));
इसके समान परिणाम प्रिंट करेगा (एनोटेशन के पैकेज के आधार पर):
null
@InheritedAnnotationType()
@InheritedAnnotationType()
_________________________________
@UninheritedAnnotationType()
null
null
ध्यान दें कि एनोटेशन को केवल कक्षाओं से विरासत में लिया जा सकता है, इंटरफेस नहीं।
एनोटेशन प्रोसेसर का उपयोग करके संकलन समय प्रसंस्करण
यह उदाहरण दर्शाता है कि एनोटेट तत्व की संकलन समय जाँच कैसे करें।
एनोटेशन
@Setter
एनोटेशन एक मार्कर है जिसे विधियों पर लागू किया जा सकता है। संकलन बाद में उपलब्ध नहीं होने के दौरान एनोटेशन को छोड़ दिया जाएगा।
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface Setter {
}
एनोटेशन प्रोसेसर
SetterProcessor
वर्ग का उपयोग संकलक द्वारा एनोटेशन को संसाधित करने के लिए किया जाता है। यह जाँचता है, अगर @Setter
एनोटेशन के साथ एनोटेट किए गए तरीके public
, गैर- static
विधियाँ जिनका नाम set
शुरू होता set
और 4 अक्षर के रूप में अपरकेस अक्षर होता है। यदि इनमें से कोई एक शर्त पूरी नहीं होती है, तो एक त्रुटि Messager
को लिखी जाती है। कंपाइलर इसे stderr को लिखता है, लेकिन अन्य टूल इस जानकारी का अलग तरह से उपयोग कर सकते हैं। उदाहरण के लिए, नेटबीन्स आईडीई उपयोगकर्ता को एनोटेशन प्रोसेसर को निर्दिष्ट करने की अनुमति देता है जिसका उपयोग संपादक में त्रुटि संदेश प्रदर्शित करने के लिए किया जाता है।
package annotation.processor;
import annotation.Setter;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
@SupportedAnnotationTypes({"annotation.Setter"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class SetterProcessor extends AbstractProcessor {
private Messager messager;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// get elements annotated with the @Setter annotation
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(Setter.class);
for (Element element : annotatedElements) {
if (element.getKind() == ElementKind.METHOD) {
// only handle methods as targets
checkMethod((ExecutableElement) element);
}
}
// don't claim annotations to allow other processors to process them
return false;
}
private void checkMethod(ExecutableElement method) {
// check for valid name
String name = method.getSimpleName().toString();
if (!name.startsWith("set")) {
printError(method, "setter name must start with \"set\"");
} else if (name.length() == 3) {
printError(method, "the method name must contain more than just \"set\"");
} else if (Character.isLowerCase(name.charAt(3))) {
if (method.getParameters().size() != 1) {
printError(method, "character following \"set\" must be upper case");
}
}
// check, if setter is public
if (!method.getModifiers().contains(Modifier.PUBLIC)) {
printError(method, "setter must be public");
}
// check, if method is static
if (method.getModifiers().contains(Modifier.STATIC)) {
printError(method, "setter must not be static");
}
}
private void printError(Element element, String message) {
messager.printMessage(Diagnostic.Kind.ERROR, message, element);
}
@Override
public void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
// get messager for printing errors
messager = processingEnvironment.getMessager();
}
}
पैकेजिंग
संकलक द्वारा लागू किए जाने के लिए, एनोटेशन प्रोसेसर को SPI को उपलब्ध कराने की आवश्यकता होती है (देखें ServiceLoader )।
ऐसा करने के लिए एक पाठ फ़ाइल META-INF/services/javax.annotation.processing.Processor
को अन्य फ़ाइल के अलावा एनोटेशन प्रोसेसर और एनोटेशन युक्त जार फ़ाइल में जोड़ने की आवश्यकता होती है। फ़ाइल को एनोटेशन प्रोसेसर के पूरी तरह से योग्य नाम को शामिल करने की आवश्यकता है, अर्थात इसे इस तरह दिखना चाहिए
annotation.processor.SetterProcessor
हम मान लेंगे कि जार फ़ाइल को नीचे AnnotationProcessor.jar
कहा जाता है।
उदाहरण एनोटेट वर्ग
निम्न वर्ग डिफ़ॉल्ट पैकेज में उदाहरण वर्ग है जिसमें अवधारण नीति के अनुसार सही तत्वों पर लागू होने वाले एनोटेशन हैं। हालाँकि केवल एनोटेशन प्रोसेसर ही दूसरी विधि को मान्य एनोटेशन लक्ष्य मानता है।
import annotation.Setter;
public class AnnotationProcessorTest {
@Setter
private void setValue(String value) {}
@Setter
public void setString(String value) {}
@Setter
public static void main(String[] args) {}
}
जेवैक के साथ एनोटेशन प्रोसेसर का उपयोग करना
यदि एनोटेशन प्रोसेसर को एसपीआई का उपयोग करके खोजा जाता है, तो इसका उपयोग स्वचालित रूप से एनोटेट तत्वों को संसाधित करने के लिए किया जाता है। उदाहरण का उपयोग करते हुए AnnotationProcessorTest
श्रेणी का संकलन
javac -cp AnnotationProcessor.jar AnnotationProcessorTest.java
निम्न आउटपुट देता है
AnnotationProcessorTest.java:6: error: setter must be public
private void setValue(String value) {}
^
AnnotationProcessorTest.java:12: error: setter name must start with "set"
public static void main(String[] args) {}
^
2 errors
सामान्य रूप से संकलन करने के बजाय। कोई .class
फ़ाइल नहीं बनाई गई है।
इसे -proc:none
को निर्दिष्ट करके रोका जा सकता है -proc:none
javac
लिए -proc:none
विकल्प -proc:none
। आप सामान्य संकलन को भी निर्दिष्ट कर सकते हैं -proc:only
।
आईडीई एकीकरण
NetBeans
एनोटेशन प्रोसेसर का उपयोग नेटबीन्स संपादक में किया जा सकता है। ऐसा करने के लिए एनोटेशन प्रोसेसर को प्रोजेक्ट सेटिंग्स में निर्दिष्ट करना होगा:
Project Properties
>Build
>Compiling
Enable Annotation Processing
Enable Annotation Processing in Editor
औरEnable Annotation Processing in Editor
लिए चेक मार्क जोड़ेंएनोटेशन प्रोसेसर सूची के आगे
Add
क्लिक करेंदिखाई देने वाले पॉपअप में एनोटेशन प्रोसेसर के पूरी तरह से योग्य वर्ग नाम दर्ज करें और
Ok
क्लिक करें।
परिणाम
एनोटेशन के पीछे का विचार
जावा लैंग्वेज स्पेसिफिकेशन एनोटेशन का वर्णन इस प्रकार है:
एनोटेशन एक मार्कर है जो सूचना को एक कार्यक्रम निर्माण के साथ जोड़ता है, लेकिन रन टाइम पर इसका कोई प्रभाव नहीं पड़ता है।
नोट प्रकार या घोषणा से पहले प्रकट हो सकते हैं। उनके लिए एक ऐसी जगह पर उपस्थित होना संभव है जहां वे एक प्रकार या घोषणा दोनों पर लागू हो सकते हैं।
वास्तव में एक एनोटेशन जो लागू होता है वह "मेटा-एनोटेशन" @Target
द्वारा नियंत्रित होता है। अधिक जानकारी के लिए "एनोटेशन प्रकार को परिभाषित करना" देखें।
एनोटेशन का उपयोग कई उद्देश्यों के लिए किया जाता है। स्प्रिंग और स्प्रिंग-एमवीसी जैसी रूपरेखाएँ परिभाषित करने के लिए एनोटेशन का उपयोग करती हैं जहां निर्भरता को इंजेक्ट किया जाना चाहिए या जहां अनुरोधों को रूट किया जाना चाहिए।
अन्य ढांचे कोड-पीढ़ी के लिए एनोटेशन का उपयोग करते हैं। लोम्बोक और जेपीए प्रमुख उदाहरण हैं, जो जावा (और एसक्यूएल) कोड उत्पन्न करने के लिए एनोटेशन का उपयोग करते हैं।
इस विषय का एक व्यापक अवलोकन प्रदान करना है:
अपने स्वयं के एनोटेशन को कैसे परिभाषित करें?
जावा भाषा क्या एनोटेशन प्रदान करती है?
अभ्यास में एनोटेशन का उपयोग कैसे किया जाता है?
'यह' और रिसीवर मापदंडों के लिए एनोटेशन
जब जावा एनोटेशन को पहली बार पेश किया गया था, तो एक आंतरिक विधि निर्माता के लिए एक इंस्टेंस विधि या छिपे हुए कंस्ट्रक्टर पैरामीटर के लक्ष्य को एनोटेट करने का कोई प्रावधान नहीं था। इसे रिसीवर पैरामीटर घोषणाओं के अलावा जावा 8 में हटा दिया गया था; देखें जेएलएस 8.4.1 ।
रिसीवर पैरामीटर एक आवृत्ति विधि या एक आंतरिक वर्ग के निर्माता के लिए एक वैकल्पिक वाक्यविन्यास उपकरण है। एक उदाहरण विधि के लिए, रिसीवर पैरामीटर उस ऑब्जेक्ट का प्रतिनिधित्व करता है जिसके लिए विधि का उपयोग किया जाता है। एक आंतरिक वर्ग के निर्माता के लिए, रिसीवर पैरामीटर नवनिर्मित वस्तु के तुरंत संलग्न उदाहरण का प्रतिनिधित्व करता है। किसी भी तरह से, रिसीवर पैरामीटर पूरी तरह से मौजूद ऑब्जेक्ट के प्रकार को स्रोत कोड में निरूपित करने की अनुमति देने के लिए मौजूद है, ताकि प्रकार को एनोटेट किया जा सके। रिसीवर पैरामीटर एक औपचारिक पैरामीटर नहीं है; अधिक सटीक रूप से, यह किसी भी प्रकार के परिवर्तनशील (.34.12.3) की घोषणा नहीं है, यह कभी भी किसी भी मान के लिए बाध्य नहीं होता है जो विधि आह्वान अभिव्यक्ति या योग्य वर्ग उदाहरण निर्माण अभिव्यक्ति में एक तर्क के रूप में पारित होता है, और इसका कोई प्रभाव नहीं पड़ता है भागो समय
निम्न उदाहरण दोनों प्रकार के रिसीवर पैरामीटर के लिए सिंटैक्स दिखाता है:
public class Outer {
public class Inner {
public Inner (Outer this) {
// ...
}
public void doIt(Inner this) {
// ...
}
}
}
रिसीवर मापदंडों का एकमात्र उद्देश्य आपको एनोटेशन जोड़ने की अनुमति देना है। उदाहरण के लिए, आपके पास एक कस्टम एनोटेशन @IsOpen
हो सकता है जिसका उद्देश्य यह दावा करना है कि किसी विधि को कॉल करने पर Closeable
ऑब्जेक्ट को बंद नहीं किया गया है। उदाहरण के लिए:
public class MyResource extends Closeable {
public void update(@IsOpen MyResource this, int value) {
// ...
}
public void close() {
// ...
}
}
एक स्तर पर, @IsOpen
पर एनोटेशन this
बस प्रलेखन के रूप में सेवा कर सकता है। हालाँकि, हम संभावित रूप से और अधिक कर सकते थे। उदाहरण के लिए:
- एनोटेशन प्रोसेसर एक रनटाइम जांच सम्मिलित कर सकता है कि
this
update
होने पर बंद स्थिति में नहीं है। - एक कोड चेकर मामलों में जहां पता लगाने के लिए एक स्थिर कोड विश्लेषण प्रदर्शन कर सकता है
this
जब बंद कर दिया जा सकता हैupdate
कहा जाता है।
कई एनोटेशन मान जोड़ें
एक एनोटेशन पैरामीटर कई मानों को स्वीकार कर सकता है यदि इसे एक सरणी के रूप में परिभाषित किया गया है। उदाहरण के लिए मानक एनोटेशन @SuppressWarnings
को इस तरह परिभाषित किया गया है:
public @interface SuppressWarnings {
String[] value();
}
value
पैरामीटर स्ट्रिंग्स का एक सरणी है। Array initializers के समान नोटेशन का उपयोग करके आप कई मान सेट कर सकते हैं:
@SuppressWarnings({"unused"})
@SuppressWarnings({"unused", "javadoc"})
यदि आपको केवल एकल मान सेट करने की आवश्यकता है, तो कोष्ठक को छोड़ा जा सकता है:
@SuppressWarnings("unused")