2017-08-02 25 views
20

बस सोच रहा है कि में घोषित चर के साथ एनोटेशन का उपयोग किस प्रकार किया जा सकता है, इसके साथ-साथ संसाधन कथन, जो इसके व्याकरण के अनुसार अनुमत है। अनुभाग 14.20.3 भाषा विनिर्देश से (जावा 7) पढ़ता है,प्रयासों के साथ प्रयास में घोषित चर पर टिप्पणियां?

TryWithResourcesStatement:
        try ResourceSpecification ब्लॉक कैच ऑप्ट अंत में ऑप्ट

ResourceSpecification :
        ( संसाधन ; ऑप्ट)

संसाधन:
        संसाधन संसाधन ; संसाधन

संसाधन:
        VariableModifiers ऑप्ट प्रकार VariableDeclaratorId = अभिव्यक्ति

और VariableModifiers (अनुभाग 14.4) के रूप में फैलता है,

VariableModifiers:
        VariableModifier
        VariableModifiers VariableModifier

VariableModifier: की
        एनोटेशन एकfinal

ये लीजिए: VariableModifierएनोटेशन हो सकता है।

try(@SomeAnnotation SomeType obj = createSomeType()) { 
    //some code 
} 

तो मेरे सवाल है: कैसे और एनोटेशन किस तरह संभवतः कोशिश के साथ-संसाधनों और व्यवहार किस तरह प्राप्त करने के लिए इस्तेमाल किया जा सकता ठीक है, कि मूल रूप से इसका मतलब है, हम कुछ इस तरह लिख सकते हैं ? कोई अभिनव विचार? क्या किसी ने उन्हें इस्तेमाल किया है?

+0

मौजूदा उत्तरों में दिए गए उदाहरणों के अतिरिक्त, यह न भूलें कि आप एनोटेशन को किसी भी अर्थ देने के लिए प्रतिबिंब का उपयोग कर सकते हैं। – Gene

+0

@ जीन जो रनटाइम पर उपलब्ध हैं, जो [स्थानीय चर] (https://docs.oracle.com/javase/specs/jls/se8/html/jls-9 के लिए मामला प्रतीत नहीं होता है) के लिए है। एचटीएमएल # जेएलएस -9.6.4.2): * स्थानीय परिवर्तनीय घोषणा पर एक टिप्पणी बाइनरी प्रतिनिधित्व में कभी नहीं बरकरार रखी जाती है। *। ऐसा लगता है कि [...] [https://stackoverflow.com/a/41776190) माइकल अर्न्स्ट (चेकर फ्रेमवर्क के लेखक) द्वारा जवाब दिया गया है, लेकिन हो सकता है कि उसका मतलब 'RetentionPolicy.CLASS' है जो चेकर्स के लिए उपयोगी है लेकिन रनटाइम पर उपलब्ध नहीं है (छोड़कर, शायद सबसे अच्छा, क्लास फ़ाइल को पार्स करके!) –

+0

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

उत्तर

14

जावा 7 में नहीं, लेकिन मुझे संदेह है कि आपने यह java-7 टैग किया है क्योंकि यह संस्करण है जिसने कोशिश की है- संसाधन, और आप जावा 7 से परे संभावित उपयोगों में अभी भी रुचि रखते हैं (मुझे लगता है कि यह प्रश्न जावा> = 8 के लिए बहुत दिलचस्प है)।

मुझे लगता है कि कुछ भी विशेष नहीं है जो संसाधनों और टिप्पणियों के साथ प्रयास करता है, यह व्याकरण में एक विशेष मामला नहीं है; इस संबंध में इस तरह के चर (एक कोशिश के साथ-संसाधनों कथन में घोषित) में अन्य स्थानीय चर के रूप में सिर्फ एक ही कर रहे हैं, और व्याकरण एनोटेशन बस के रूप में अच्छी तरह से की अनुमति देता है:

  • जावा 7 शुरू की है कोशिश के साथ-संसाधनों बयान , जिसमें आप एक चर घोषित कर सकते हैं जो special treatment प्राप्त करेगा।
  • व्याकरण स्थानीय चर घोषणाओं पर एनोटेशन की इजाजत दी गई है के रूप में जल्दी जावा 5, जब एनोटेशन शुरू किए गए थे (लेकिन हम जावा 6 प्रतीक्षा करने के लिए एनोटेशन प्रसंस्करण के लिए एक उपयोगी एपीआई पाने के लिए था)
  • लेकिन फिर भी जावा 7 के साथ के रूप में यह स्थानीय चर पर एनोटेशन तक पहुंचने के लिए एनोटेशन प्रोसेसर के लिए not possible था। स्थानीय चर पर एकमात्र एनोटेशन जो "उपयोग करने योग्य" था @SuppressWarnings था लेकिन उसमें विशेष रूप से संकलक द्वारा स्वयं का इलाज किया गया था, इसमें आपके लिए कोई रास्ता नहीं था।
  • जावा 8 के अलावा "घोषणा संदर्भ", वहाँ अब है "प्रकार संदर्भ", और अब एक एनोटेशन TargetElementType.TYPE_USE

तो जवाब (जावा 8) के साथ हो सकता है एनोटेशन संदर्भ की एक नई तरह की शुरुआत की स्थानीय चर पर किसी भी टिप्पणी के साथ ही है।


(जावा 8 के नए "प्रकार एनोटेशन" के बारे में कुछ सामान्य ज्ञान)

... और यह वह जगह है जहाँ यह दिलचस्प हो जाता है: किसी भी प्रकार के उपयोग व्याख्या!

वाक्यात्मक स्थानों में जहां एनोटेशन दिखाई दे सकते हैं घोषणा में विभाजित हैं,, जहां एनोटेशन घोषणाओं के लिए लागू संदर्भों और प्रकार, जहां एनोटेशन घोषणाओं और भाव में इस्तेमाल प्रकारों पर लागू संदर्भों।

ऐसी टिप्पणियां रनटाइम पर नहीं रखी जाती हैं, लेकिन विभिन्न प्रकार के "चेक" के लिए संकलन-समय पर उपयोग की जा सकती हैं। checker framework देखें, जो JSR-308 के लिए किए गए काम के शीर्ष पर बनाया गया है (same author द्वारा यदि मैं सही ढंग से समझता हूं)।

बहुत जल्दी है क्योंकि यह मजेदार है, अब हम यह कर सकते हैं:

@NonNull Object @Nullable [] array; // Nullable array of non-null objects 
@Nullable Object @NonNull [] array; // Non-null array of nullable objects 

@Foo List<@Foo Integer> doSomething(@Foo Integer @Foo [] arrayOfIntegers, @Foo long x) { 
    arrayOfIntegers[0] = (@Foo int) x; 
    return Arrays.asList(arrayOfIntegers); 
} 

ऐसे "type annotations" के उदाहरण:

परीक्षक फ्रेमवर्क कुछ प्रकार टिप्पणियां जो दोनों पुस्तकालय और एप्लिकेशन डेवलपर फायदा हो सकता है प्रदान करता है , जैसे:
@NonNull - संकलक उन मामलों को निर्धारित कर सकता है जहां कोड पथ को शून्य मान प्राप्त हो सकता है, बिना किसी NullPointerException को डीबग किए।
@ReadOnly - कंपाइलर वस्तु को बदलने के किसी भी प्रयास को ध्वजांकित करेगा। यह Collections.unmodifiableList के समान है, लेकिन संकलन समय पर अधिक सामान्य और सत्यापित है।
@Regex - संकलन-समय सत्यापन प्रदान करता है कि नियमित अभिव्यक्ति के रूप में उपयोग किए जाने वाले स्ट्रिंग को एक उचित स्वरूपित नियमित अभिव्यक्ति है।
@Tainted और @Untainted - डेटा के पहचान प्रकार जिन्हें एक साथ उपयोग नहीं किया जाना चाहिए, जैसे रिमोट यूजर इनपुट सिस्टम कमांड में इस्तेमाल किया जा रहा है, या लॉग स्ट्रीम में संवेदनशील जानकारी।
@m - माप की इकाइयां यह सुनिश्चित करती हैं कि वस्तुओं को मापने के लिए उपयोग की जाने वाली संख्याओं का उपयोग सही ढंग से किया जाता है और उचित इकाई रूपांतरण से गुजरता है।

लेकिन उनमें से कोई भी विशेष रूप से प्रयास-संसाधन-संसाधन कथन के संदर्भ में उपयोगी नहीं है (मेरा मतलब है, कहीं और कहीं भी कम नहीं)।


प्रश्न पर वापस वहाँ स्थानीय चर कि विशेष रूप से दिलचस्प जब एक कोशिश के साथ-संसाधनों कथन में घोषित किया जाएगा पर एनोटेशन के लिए उपयोग करता है?

मैं इस मामले में लगता है कि आवेदन पत्र अनिवार्य रूप से सीमित करने के लिए संकलन-समय जांचें करता होगा, क्योंकि इस तरह एक एनोटेशन स्थानीय चर पर या तो हो जाएगा, या प्रकार उपयोग पर, और न तो रनटाइम पर उपलब्ध है (या नहीं वास्तव में):

  • स्थानीय चर पर according to the JLS एनोटेशन प्रकार उपयोग करता है पर द्विआधारी प्रतिनिधित्व में बने नहीं रहते हैं
  • एनोटेशन written to the class file, लेकिन still not available at runtime by reflection (आप वर्ग अपने आप को फ़ाइल को पार्स करने की आवश्यकता होगी)
  • कर रहे हैं! 10

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

/* Say getResponse() taps into a third-party library that has a quirk: 
* a response object must be consumed entirely before being closed. */ 
try(@MustConsumeEntirely Stream<String> lines = getResponse()) { 
    lines.findFirst().ifPresent(System.out::println); 
    /* The stream is not entirely consumed (unless it is only 1 line but there is no way to tell). 
    * A smart checker could catch this and issue a warning. */ 
} 

यह एनोटेशन लक्ष्य ElementType.LOCAL_VARIABLE होता (ताकि नया जावा 8 टिप्पणी प्रकार की आवश्यकता नहीं होगी, लेकिन जावा 8 की आवश्यकता होती है processeable होने के लिए होता है), और चेकर शायद सत्यापित करना चाहिए कि चर प्रभावी रूप से एक try- भीतर घोषित किया जाता है संसाधन संसाधन के साथ (संकलक किसी भी स्थानीय चर पर इसका उपयोग करने से नहीं रोका जा सकता है), और उसके बाद स्रोत पेड़ का विश्लेषण यह निर्धारित करने के लिए करें कि संसाधनों को आवश्यकतानुसार उपभोग किया जाता है या नहीं।
इस तरह के चेकर को 100% सही तरीके से कार्यान्वित करना संभवतः असंभव होगा, लेकिन पेपर पर कुछ ज्ञात-खराब पैटर्न की जांच करना संभव लगता है, और यह ज्यादातर समझ में आता है जब लक्ष्य चर को एक कोशिश में घोषित किया जाता है- संसाधन संसाधन के साथ।

एक और विचार (अभी भी परिवर्तनीय और प्रकार के उपयोग पर नहीं), बहुत कम उपयोगिता: @MustNotEscape, यदि आप यह नियंत्रित करना चाहते हैं कि चर किसी अन्य विधि को पारित नहीं किया गया है (उपर्युक्त के कारणों के लिए) आप क्षमता चाहते हैं ऑब्जेक्ट के पीछे होने वाली हर चीज को नियंत्रित करने के लिए (उदाहरण के लिए पिछले विचार में), और यदि चर के चारों ओर पारित किया जाता है तो इसे पूरा करना अधिक कठिन होगा।

यह स्पष्ट करने के लिए कि ऐसी चीज बेहद संभव है, here is an example एक ढांचे के बारे में जो आपको उम्मीद है कि आप एक निश्चित ब्लॉक के अंदर अपने "एम्बेडेड डीएसएल" का पालन करना चाहते हैं, और fails यदि आप नहीं करते हैं। एक संसाधन के साथ एक संसाधन पर एक hypothetical ढांचे द्वारा लगाए गए समान बाधाओं के अनुपालन की जांच करने में मदद करने के लिए एक एनोटेशन की कल्पना कर सकता है।
कह नहीं यह हालांकि एक अच्छा डिजाइन किया जाएगा ...

(मैं ModelMapper के मामले, डीएसएल केवल एक चतुर चाल के साथ वे जावा 8, और वे पहले अब lambdas के साथ बेहतर & सुरक्षित समाधान है आया था)
5

एकमात्र प्रकार की एनोटेशन जो आप स्थानीय चर पर लागू कर सकते हैं (जिसमें try के साथ एक संसाधन असाइनमेंट शामिल है) जिसमें @Target({ElementType.LOCAL_VARIABLE}) है। और वे रनटाइम (प्रतिबिंब के माध्यम से) पर उपलब्ध नहीं हैं, इसलिए उन्हें केवल कंपाइलर द्वारा ही एक्सेस किया जा सकता है।

उदाहरण के लिए जब वे उपयोगी हो सकता है:

  • @SuppressWarnings("unchecked") - यदि आप एक try(...)
  • भीतर अनियंत्रित काम एनोटेशन JSR 305 (सॉफ्टवेयर दोष का पता लगाने के लिए की जाने वाली टिप्पणियां), जैसे @Nullable, का उपयोग करना है, तो @Nonnull
संबंधित मुद्दे