2009-07-24 11 views
62

मुझे त्रुटि क्यों मिल रही है "विशेषता मान स्थिर होना चाहिए"। शून्य निरंतर ???एनोटेशन के फ़ील्ड के लिए डिफ़ॉल्ट शून्य मान सेट करने में त्रुटि

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface SomeInterface { 
    Class<? extends Foo> bar() default null;// this doesn't compile 
} 

उत्तर

52

मैं पता नहीं क्यों, लेकिन JLS बहुत स्पष्ट है:

Discussion 

Note that null is not a legal element value for any element type. 

और एक डिफ़ॉल्ट तत्व की परिभाषा है:

 DefaultValue: 
     default ElementValue 

दुर्भाग्य से मुझे लगता है कि नई भाषा सुविधाओं ढूंढ पाएं (एनम्स और अब एनोटेशन) में बहुत ही अनुपयोगी कंपाइलर त्रुटि संदेश होते हैं जब आप भाषा की कल्पना को पूरा नहीं करते हैं।

संपादित करें: एक छोटी सी googleing JSR-308 है, जहां वे इस स्थिति में nulls की अनुमति के लिए बहस में following पाया:

हम प्रस्ताव के कुछ संभावित आपत्तियों को नोट करें।

प्रस्ताव कुछ भी संभव नहीं बनाता है जो पहले संभव नहीं था।

प्रोग्रामर से परिभाषित विशेष मान शून्य की तुलना में बेहतर प्रलेखन, जो मतलब हो सकता है प्रदान करता है "कोई नहीं", "अप्रारंभीकृत", जो अपने आप अशक्त, आदि

प्रस्ताव है अधिक त्रुटि प्रवण। एक स्पष्ट मूल्य की जांच भूलना भूलने के बजाय शून्य के खिलाफ जांचना भूलना बहुत आसान है।

प्रस्ताव मानक मुहावरे अधिक वर्बोज़ बना सकता है। वर्तमान में केवल एनोटेशन के उपयोगकर्ताओं को अपने विशेष मूल्यों की जांच करने की आवश्यकता है। प्रस्ताव के साथ, एनोटेशन को संसाधित करने वाले कई टूल को यह जांचना होगा कि क्या फ़ील्ड का मान शून्य है या नहीं, न कि वे एक शून्य सूचक अपवाद फेंक दें।

मुझे लगता है कि केवल अंतिम दो बिंदु प्रासंगिक हैं "इसे पहले स्थान पर क्यों न करें।" आखिरी बिंदु निश्चित रूप से एक अच्छा मुद्दा लाता है - एक एनोटेशन प्रोसेसर को कभी भी चिंतित नहीं होना चाहिए कि उन्हें एनोटेशन वैल्यू पर शून्य मिल जाएगी। मुझे लगता है कि एनोटेशन प्रोसेसर और अन्य ऐसे फ्रेमवर्क कोड के काम के रूप में डेवलपर कोड को दूसरी तरफ के बजाय स्पष्ट करने के लिए उस तरह की जांच करना है, लेकिन यह निश्चित रूप से इसे बदलने के लिए उचित बनाना होगा।

41

ऐसा लगता है कि यह अवैध है, हालांकि जेएलएस इस पर बहुत अस्पष्ट है।

मैं अपने स्मृति भरे कोशिश करते हैं और वहाँ एक मौजूदा टिप्पणी कि एक एनोटेशन करने के लिए एक वर्ग विशेषता थी के बारे में सोचना है, और JAXB एपीआई से इस एक याद किया:

@Retention(RUNTIME) @Target({PACKAGE,FIELD,METHOD,TYPE,PARAMETER})   
public @interface XmlJavaTypeAdapter { 
    Class type() default DEFAULT.class; 

    static final class DEFAULT {}  
} 

आप देख सकते हैं कि वे किस तरह है एक डमी के बराबर पकड़ने के लिए एक डमी स्थिर वर्ग को परिभाषित करना पड़ा।

अप्रिय।

+2

हां, हम कुछ ऐसा करते हैं (हम केवल Foo.class को डिफ़ॉल्ट के रूप में उपयोग करते हैं)। बेकार है। – ripper234

+5

और स्ट्रिंग फ़ील्ड के मामले में, आपको [जादू तार] (http://en.wikipedia.org/wiki/Magic_string) का सहारा लेना होगा। स्पष्ट रूप से जाने-माने एंटीपेटर्न अब अच्छी तरह से समझी जाने वाली भाषा सुविधाओं से बेहतर हैं। –

+2

@TimYates यह मुझे लोगों को अपने "कोई मूल्य" सेंटीनेल मूल्य को परिभाषित करने के लिए मारता है जब शून्य उपलब्ध होता है और सार्वभौमिक रूप से समझा जाता है। और अब भाषा की आवश्यकता है ?! सौभाग्य से, आप अपने "जादू तार" को सार्वजनिक स्थिरांक के रूप में परिभाषित कर सकते हैं। यह अभी भी आदर्श नहीं है लेकिन कम से कम वह कोड जो आपकी एनोटेशन की तलाश में है, हर जगह अक्षर का उपयोग करने के बजाय निरंतर संदर्भित कर सकता है। – spaaarky21

46

इस

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface SomeInterface { 
    Class bar() default void.class; 
} 

यह एक नया वर्ग की आवश्यकता नहीं है की कोशिश करो और यह पहले से ही जावा में एक कीवर्ड के लिए कुछ भी नहीं मतलब है कि है।

+6

मुझे यह पसंद है। एकमात्र समस्या - मूल प्रश्न के संदर्भ में - यह है कि यह उत्तर प्रकार पैरामीटर का समर्थन नहीं करता है: 'कक्षा bar() डिफ़ॉल्ट void.null' संकलित नहीं करता है। – Kariem

+1

void.class आमतौर पर लागू नहीं किया जा सकता है: सार्वजनिक @interface NoNullDefault {स्ट्रिंग मान() डिफ़ॉल्ट void.class; } – wjohnson

+0

ग्रोवी के लिए यह ठीक काम करता है, यहां तक ​​कि टिप्पणियों में उल्लिखित मामलों में भी – Vampire

9

ऐसा लगता है कि ऐसा करने का एक और तरीका है।

मुझे यह पसंद नहीं है, लेकिन यह काम कर सकता है।

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface SomeInterface { 
    Class<? extends Foo>[] bar() default {}; 
} 

तो मूल रूप से आप इसके बजाय एक खाली ऐरे बनाते हैं। ऐसा लगता है कि एक डिफ़ॉल्ट मान की अनुमति है।

1

वह त्रुटि संदेश भ्रामक है, लेकिन, नहीं, null शाब्दिक जावा भाषा विशिष्टता, here में परिभाषित एक निरंतर अभिव्यक्ति नहीं है।

इसके अलावा, Java Language Specification कहते

यह एक संकलन समय त्रुटि है अगर तत्व के प्रकार के अनुरूप नहीं है (§9.7) निर्दिष्ट डिफ़ॉल्ट मान के साथ।

और explain what that means

को यह एक संकलन समय त्रुटि अगर तत्व प्रकार तत्व मूल्य के अनुरूप नहीं है।

  • [...]
  • वी नहीं अशक्त है: एक तत्व प्रकार टी एक तत्व मूल्य वी यदि और केवल यदि निम्न में से एक सच है के अनुरूप है।

तो यहाँ, अपने तत्व प्रकार, Class<? extends Foo>, नहीं डिफ़ॉल्ट मान के अनुरूप है, क्योंकि वह मूल्य null है।

+0

क्या मुझे कुछ गलत मिला? –

+0

आपका समाधान कॉपी और पेस्ट के लिए उपयुक्त नहीं है ;-) कुछ पढ़ने पर, पसंद नहीं करते हैं –

0
Class<? extends Foo> bar() default null;// this doesn't compile 

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

मुझे क्या करना है एनोटेशन परिभाषा के शीर्ष पर DEFAULT_VALUE स्थिरांक को परिभाषित करना है। कुछ की तरह:

public static final String DEFAULT_VALUE = "__class-name-here__ default"; 

public String prefix() default DEFAULT_VALUE; 
तब मेरे कोड में

मैं की तरह कुछ कार्य करें: एक वर्ग के साथ

if (myAnnotation.prefix().equals(MyAnnotation.DEFAULT_VALUE)) { ... } 

आप मामले में, मैं सिर्फ एक मार्कर वर्ग को परिभाषित करेगा। दुर्भाग्य से आप इस के लिए एक निरंतर तो बजाय आप की तरह कुछ करने की ज़रूरत नहीं हो सकता है:

Class<? extends Foo> bar() default DefaultFoo.class; 

आपका DefaultFoo वर्ग ताकि कोड कर सकते हैं होगा सिर्फ एक खाली कार्यान्वयन:

if (myAnnotation.bar() == DefaultFoo.class) { ... } 

इस आशा किसी और की मदद करता है।

संबंधित मुद्दे

 संबंधित मुद्दे