मुझे एक त्रुटि क्यों मिल रही है "गुण मान स्थिर होना चाहिए"। अशक्त नहीं है ???
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class<? extends Foo> bar() default null;// this doesn't compile
}
मुझे एक त्रुटि क्यों मिल रही है "गुण मान स्थिर होना चाहिए"। अशक्त नहीं है ???
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class<? extends Foo> bar() default null;// this doesn't compile
}
जवाबों:
मुझे पता नहीं क्यों, लेकिन जेएलएस बहुत स्पष्ट है:
Discussion
Note that null is not a legal element value for any element type.
और एक डिफ़ॉल्ट तत्व की परिभाषा है:
DefaultValue:
default ElementValue
दुर्भाग्य से मुझे पता चलता है कि जब आप भाषा से नहीं जुड़ते हैं तो नई भाषा की विशेषताएँ (एनम और अब एनोटेशन) में बहुत ही बेकार कम्पाइलर त्रुटि संदेश होते हैं।
संपादित करें: JSR-308 में थोड़ा सा Googleing निम्नलिखित पाया गया , जहां वे इस स्थिति में नल की अनुमति देने के लिए तर्क देते हैं:
हम प्रस्ताव पर कुछ संभावित आपत्तियों पर ध्यान देते हैं।
प्रस्ताव कुछ भी संभव नहीं बनाता है जो पहले संभव नहीं था।
प्रोग्रामर-परिभाषित विशेष मूल्य शून्य से बेहतर प्रलेखन प्रदान करता है, जिसका अर्थ हो सकता है "कोई नहीं", "असिंचित", स्वयं को शून्य, आदि।
प्रस्ताव अधिक त्रुटिपूर्ण है। एक स्पष्ट मूल्य के लिए जाँच करने की तुलना में अशक्त के खिलाफ जाँच को भूलना बहुत आसान है।
प्रस्ताव मानक मुहावरे को और अधिक क्रियाशील बना सकता है। वर्तमान में केवल एनोटेशन के उपयोगकर्ताओं को इसके विशेष मूल्यों की जांच करने की आवश्यकता है। प्रस्ताव के साथ, एनोटेशन की प्रक्रिया करने वाले कई उपकरणों को यह जांचना होगा कि किसी फ़ील्ड का मान अशक्त है या नहीं, वे एक शून्य सूचक अपवाद को फेंक देते हैं।
मुझे लगता है कि केवल अंतिम दो बिंदु "पहले स्थान पर क्यों नहीं" के लिए प्रासंगिक हैं। अंतिम बिंदु निश्चित रूप से एक अच्छा बिंदु लाता है - एक एनोटेशन प्रोसेसर को कभी भी चिंतित नहीं होना पड़ता है कि उन्हें एनोटेशन मूल्य पर एक अशक्त मिलेगा। मैं देख रहा हूं कि एनोटेशन प्रोसेसर और इस तरह के अन्य फ्रेमवर्क कोड के रूप में अधिक काम करने के लिए डेवलपर्स कोड को स्पष्ट करने के लिए उस तरह की जांच करनी होगी, बजाय इसके कि अन्य तरीके से, लेकिन यह निश्चित रूप से इसे बदलने का औचित्य साबित करने के लिए कठिन बना देगा।
इसे इस्तेमाल करे
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class bar() default void.class;
}
इसके लिए किसी नए वर्ग की आवश्यकता नहीं है और यह जावा में पहले से ही एक कीवर्ड है जिसका अर्थ है कुछ भी नहीं।
Class<? extends Foo> bar() default void.null
नहीं करता है : संकलन नहीं करता है।
ऐसा लगता है कि यह अवैध है, हालांकि जेएलएस इस पर बहुत फजी है।
मैंने एक मौजूदा एनोटेशन के बारे में सोचने की कोशिश करने के लिए अपनी मेमोरी को मिटा दिया, जिसमें एनोटेशन के लिए एक क्लास विशेषता थी, और इसे JAXB API से याद किया गया था:
@Retention(RUNTIME) @Target({PACKAGE,FIELD,METHOD,TYPE,PARAMETER})
public @interface XmlJavaTypeAdapter {
Class type() default DEFAULT.class;
static final class DEFAULT {}
}
आप देख सकते हैं कि एक अशक्त के बराबर धारण करने के लिए उन्हें एक डमी स्थिर वर्ग को कैसे परिभाषित करना था।
अप्रिय।
ऐसा लगता है कि इसे करने का एक और तरीका है।
मुझे यह पसंद नहीं है, लेकिन यह काम कर सकता है।
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class<? extends Foo>[] bar() default {};
}
तो मूल रूप से आप इसके बजाय एक खाली ऐरे बनाते हैं। यह एक डिफ़ॉल्ट मान की अनुमति देता है।
Class<? extends Foo> bar() default null;// this doesn't compile
जैसा कि उल्लेख किया गया है, जावा भाषा विनिर्देश एनोटेशन डिफॉल्ट में अशक्त मूल्यों की अनुमति नहीं देता है।
मैं जो करना चाहता हूं DEFAULT_VALUE
वह है एनोटेशन परिभाषा के शीर्ष पर स्थिरांक को परिभाषित करना । कुछ इस तरह:
public @interface MyAnnotation {
public static final String DEFAULT_PREFIX = "__class-name-here__ default";
...
public String prefix() default DEFAULT_PREFIX;
}
फिर मेरे कोड में मैं कुछ ऐसा करता हूं:
if (myAnnotation.prefix().equals(MyAnnotation.DEFAULT_PREFIX)) { ... }
एक वर्ग के साथ आपके मामले में, मैं सिर्फ एक मार्कर वर्ग को परिभाषित करूंगा। दुर्भाग्य से आपके पास इसके लिए एक स्थिरांक नहीं हो सकता है इसके बजाय आपको कुछ ऐसा करने की आवश्यकता है:
public @interface MyAnnotation {
public static Class<? extends Foo> DEFAULT_BAR = DefaultBar.class;
...
Class<? extends Foo> bar() default DEFAULT_BAR;
}
आपकी DefaultFoo
कक्षा केवल एक खाली कार्यान्वयन होगी ताकि कोड कर सकें:
if (myAnnotation.bar() == MyAnnotation.DEFAULT_BAR) { ... }
उम्मीद है की यह मदद करेगा।
.equals()
और नहीं ==
? क्या आपको एक अलग मूल्य या एक अलग वस्तु मिली ।
==
।
.equals()
। चौंका देने वाला।
यह त्रुटि संदेश भ्रामक है, लेकिन, नहीं, null
शाब्दिक एक स्थिर अभिव्यक्ति नहीं है, जैसा कि जावा भाषा विनिर्देश में परिभाषित किया गया है, यहां ।
इसके अलावा, जावा लैंग्वेज स्पेसिफिकेशन कहता है
यह एक संकलित-समय की त्रुटि है यदि तत्व का प्रकार निर्दिष्ट डिफ़ॉल्ट मान के साथ कम्यूटेट (.79.7) नहीं है ।
और यह समझाने के लिए कि इसका क्या मतलब है
यदि तत्व प्रकार तत्व मान के अनुरूप नहीं है तो यह एक संकलन-समय त्रुटि है। एक तत्व प्रकार T एक तत्व मान के साथ V है और यदि केवल निम्न में से कोई एक सत्य है:
T
एक सरणी प्रकार हैE[]
, और या तो:
- [...]
T
एक सरणी प्रकार नहीं है , औरV
असाइनमेंट का प्रकार ()5.2) संगत हैT
, और :
- यदि
T
एक आदिम प्रकार है याString
, तोV
एक स्थिर अभिव्यक्ति है (.215.28)।- अगर
T
हैClass
या की एक मंगलाचरणClass
(§4.5), तोV
एक वर्ग शाब्दिक (§15.8.2) है।- यदि
T
एक एनुम प्रकार (.98.9) है, तोV
एक एनम स्थिरांक (en8.9.1) है।- V शून्य नहीं है ।
तो यहां, आपका तत्व प्रकार, Class<? extends Foo>
डिफ़ॉल्ट मान के अनुरूप नहीं है, क्योंकि वह मान है null
।
or
और एक आंतरिक है and
, जिसे बाहर नहीं छोड़ा जा सकता है।
जैसा कि दूसरों ने कहा है, एक नियम है जो कहता है कि शून्य जावा में मान्य डिफ़ॉल्ट मान नहीं है।
यदि आपके पास सीमित संख्या में संभावित मान हैं, जो क्षेत्र में हो सकते हैं , तो इसके लिए काम करने का एक विकल्प यह है कि फ़ील्ड प्रकार को कस्टम एनम बनाया जाए जिसमें स्वयं एक नल शामिल है। उदाहरण के लिए, कल्पना करें कि मेरे पास निम्नलिखित एनोटेशन है जिसके लिए मुझे एक डिफ़ॉल्ट अशांति चाहिए:
public @interface MyAnnotation {
Class<?> value() default null;
}
जैसा कि हमने स्थापित किया है, इसकी अनुमति नहीं है। इसके बजाय हम क्या कर सकते हैं परिभाषित करना है:
public enum MyClassEnum {
NULL(null),
MY_CLASS1(MyClass1.class),
MY_CLASS2(MyClass2.class),
;
public final Class<?> myClass;
MyClassEnum(Class<?> aClass) {
myClass = aClass;
}
}
और एनोटेशन को इस तरह बदलें:
public @interface MyAnnotation {
MyClassEnum value() default MyClassEnum.NULL;
}
इसका मुख्य नकारात्मक पहलू (आपके संभावित मूल्यों को मानने की आवश्यकता से) यह है कि आपने अब अपने मान को एनम में लपेट लिया है, इसलिए आपको मान प्राप्त करने के लिए एनम पर संपत्ति / प्राप्तकर्ता को आमंत्रित करना होगा।
Class<? extends Foo> bar();
।