एक तत्व पर एक ही प्रकार के एकाधिक एनोटेशन?


91

मैं एक ही तत्व पर एक ही प्रकार के दो या अधिक एनोटेशन को थप्पड़ मारने का प्रयास कर रहा हूं, इस मामले में, एक विधि। यहाँ अनुमानित कोड है जिसके साथ मैं काम कर रहा हूँ:

public class Dupe {
    public @interface Foo {
      String bar();
    }

    @Foo(bar="one")
    @Foo(bar="two")
    public void haha() {}
}

उपरोक्त संकलन करते समय, javac एक डुप्लिकेट एनोटेशन के बारे में शिकायत करता है:

max @ upsight: ~ / काम / दिन के बहाने $ javac Dupe.java 
डुपए.जावा और: डुप्लिकेट एनोटेशन

क्या इस तरह से एनोटेशन दोहराना संभव नहीं है? पांडित्यपूर्ण रूप से, उनकी सामग्री भिन्न होने के कारण @Foo के दो उदाहरण अलग-अलग नहीं हैं?

यदि उपरोक्त संभव नहीं है, तो कुछ संभावित वर्कअराउंड क्या हैं?

अद्यतन: मुझे अपने उपयोग के मामले का वर्णन करने के लिए कहा गया है। यहाँ जाता हैं।

मैं MongoDB जैसे दस्तावेज़ स्टोर के POJOs को "मैप" करने के लिए एक वाक्यविन्यास शर्करा तंत्र का निर्माण कर रहा हूं। मैं अनुक्रमणिका को गेटर्स या सेटर पर एनोटेशन के रूप में निर्दिष्ट करने की अनुमति देना चाहता हूं। यहाँ एक उदाहरण दिया गया है:

public class Employee {
    private List<Project> projects;

    @Index(expr = "project.client_id")
    @Index(expr = "project.start_date")
    public List<Project> getProjects() { return projects; }
}

जाहिर है, मैं परियोजना के विभिन्न गुणों द्वारा कर्मचारी के उदाहरणों को जल्दी से ढूंढना चाहता हूं। मैं या तो अलग-अलग expr () मानों के साथ @ दो बार निर्दिष्ट कर सकता हूं, या स्वीकृत उत्तर में निर्दिष्ट दृष्टिकोण ले सकता हूं। भले ही हाइबरनेट ऐसा करता है और इसे हैक नहीं माना जाता है, मुझे लगता है कि यह अभी भी कम से कम एक ही तत्व पर एक ही प्रकार के कई एनोटेशन होने की अनुमति देता है।


1
इस डुप्लिकेट नियम को जावा 7 में अपने प्रोग्राम को अनुमति देने के लिए आराम करने का प्रयास है। क्या आप कृपया अपने उपयोग के मामले का वर्णन कर सकते हैं?
नॉटेनोप

मैंने अपने प्रश्न को इस विवरण के साथ संपादित किया है कि मैं ऐसा क्यों करना चाहता हूं। धन्यवाद।
मैक्स ए।

सीडीआई में कई क्वालीफायर के लिए बीन प्रदान करने की अनुमति देना आसान हो सकता है। उदाहरण के लिए, मैंने दो स्थानों पर सेम को पुन: उपयोग करने की कोशिश की है, इसे "@Packages @PackageName (" test1 ") @PackageName (" test2 ")"
रिचर्ड कोरफील्ड

आगे: नीचे दिए गए उत्तर से उस समस्या का समाधान नहीं होता है क्योंकि CDI समग्र को एक क्वालिफायर के रूप में देखता है।
रिचर्ड कोरफील्ड

@MaxA। कृपया अपनी "ग्रीन चेक" स्वीकृति को मर्न्स्ट द्वारा सही उत्तर में बदलें। जावा 8 ने एनोटेशन दोहराने की क्षमता को जोड़ा।
तुलसी बोर्क

जवाबों:


140

एक ही प्रकार के दो या अधिक एनोटेशन की अनुमति नहीं है। हालाँकि, आप ऐसा कुछ कर सकते हैं:

public @interface Foos {
    Foo[] value();
}

@Foos({@Foo(bar="one"), @Foo(bar="two")})
public void haha() {}

यद्यपि आपको कोड में फ़ॉउस एनोटेशन के समर्पित हैंडलिंग की आवश्यकता होगी।

btw, मैं सिर्फ इस 2 घंटे पहले इस्तेमाल किया है एक ही समस्या के आसपास काम :)


2
क्या आप ग्रूवी में भी ऐसा कर सकते हैं?
Excel20

5
@ Excel20 हाँ। आपको वर्ग कोष्ठक का उपयोग करना होगा, हालांकि, उदाहरण के लिए @Foos([@Foo(bar="one"), @Foo(bar="two")])। देखें groovy.codehaus.org/Annotations+with+Groovy
sfussenegger

दिन में थोड़ी देर लेकिन सलाह की ओर इशारा करने की परवाह है जो फू के अंदर फू की सूची को संसाधित कर सकता है? फिलहाल मैं एक विधि के परिणाम को रियायत देने की कोशिश कर रहा हूं, लेकिन यद्यपि फू को इंटरसेप्ट किया जाता है फू सलाह कभी दर्ज नहीं की जाती है
स्टेलियोस कुसौरिस

अपडेट: जावा 8 के रूप में, यह उत्तर पुराना है। Mernst द्वारा सही आधुनिक उत्तर देखें । जावा 8 ने एनोटेशन दोहराने की क्षमता को जोड़ा।
तुलसी बोर्क

65

जावा 8 में बार-बार एनोटेशन

में जावा 8 (मार्च 2014 में जारी किया गया), यह दोहराया / डुप्लीकेट एनोटेशन लिखने के लिए संभव है।

ट्यूटोरियल देखें, बार-बार एनोटेशन

विनिर्देश देखें, JEP 120: बार-बार व्याख्याएँ


1
आधिकारिक दस्तावेज़ docs.oracle.com/javase/tutorial/java/annotations/repeating.html
एंडरसन

21

उल्लिखित अन्य तरीकों के अलावा, Java8 में एक और कम क्रिया तरीका है:

@Target(ElementType.TYPE)
@Repeatable(FooContainer.class)
@Retention(RetentionPolicy.RUNTIME)
@interface Foo {
    String value();

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface FooContainer {
        Foo[] value();
        }

@Foo("1") @Foo("2") @Foo("3")
class Example{

}

डिफ़ॉल्ट रूप से उदाहरण मिलता है, FooContainerएनोटेशन के रूप में

    Arrays.stream(Example.class.getDeclaredAnnotations()).forEach(System.out::println);
    System.out.println(Example.class.getAnnotation(FooContainer.class));

उपरोक्त दोनों प्रिंट:

@ com.FooContainer (मान = [@ com.Foo (value = 1), @ com.Foo (मान = 2), @ com.Foo (मान = 3)])

@ com.FooContainer (मान = [@ com.Foo (value = 1), @ com.Foo (मान = 2), @ com.Foo (मान = 3)])


यह इंगित करने के लायक है कि FooContainer में विधि / क्षेत्र का नाम "मूल्य ()" नाम का सख्त होना चाहिए। अन्यथा फू संकलन नहीं होगा।
टॉमाज़ मूलारस्क 11

... एनोटेशन प्रकार (FooContainer) भी दोहराए एनोटेशन प्रकार (Foo) से अधिक प्रकार के लिए लागू नहीं किया जा सकता।
टॉमाज़ मूलरस्क

16

http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html

Java8 से शुरू होकर आप दोहराए जाने वाले एनोटेशन का वर्णन कर सकते हैं:

@Repeatable(FooValues.class)
public @interface Foo {
    String bar();
}

public @interface FooValues {
    Foo[] value();
}

ध्यान दें, value मान सूची के लिए आवश्यक फ़ील्ड है।

अब आप सरणी भरने के बजाय उन्हें दोहराने वाले एनोटेशन का उपयोग कर सकते हैं:

@Foo(bar="one")
@Foo(bar="two")
public void haha() {}

12

जैसा कि sfussenegger ने कहा है, यह संभव नहीं है।

सामान्य समाधान "एकाधिक" एनोटेशन का निर्माण करना है , जो पिछले एनोटेशन की एक सरणी को संभालता है। आमतौर पर इसे 's' प्रत्यय के साथ नाम दिया गया है।

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


अपनी आवश्यकताओं के आधार पर, कई मूल्यों को संभालने के लिए अपने पहले एनोटेशन की अनुमति देना बेहतर हो सकता है ।

उदाहरण:

    public @interface Foo {
      String[] bars();
    }

मुझे पता था कि यह पूरी तरह से परिचित था। मेरी स्मृति को ताज़ा करने के लिए धन्यवाद।
मैक्स ए।

अब यह जावा 8 के साथ संभव है।
अनीस

4

अन्य उत्तरों को सरलतम रूप में संयोजित करना ... मूल्यों की एक सरल सूची के साथ एक एनोटेशन ...

@Foos({"one","two"})
private String awk;

//...

public @interface Foos{
    String[] value();
}

3

यदि आपके पास केवल 1 पैरामीटर "बार" है, तो आप इसे "मान" नाम दे सकते हैं। जब आप इसे इस तरह से उपयोग करते हैं तो इस मामले में आपको पैरामीटर का नाम लिखना होगा:

@Foos({@Foo("one"), @Foo("two")})
public void haha() {}

थोड़ा छोटा और निरर्थक, इम्हो ।।


सही बिंदु, लेकिन यह ओपी के सवाल का जवाब देने का प्रयास कैसे करता है?
मोर्दकै

@MouseEvent आप सही हैं, मुझे लगता है कि यह sfussenegger से शीर्ष उत्तर के सुधार का अधिक था और इस प्रकार वहाँ टिप्पणियों में अधिक है। लेकिन
रिपोटेबल

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