कारण Optional
जावा में जोड़ा गया था क्योंकि यह है:
return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.getOrThrow(() -> new InternalError(...));
इस से क्लीनर है:
Method matching =
Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.getFirst();
if (matching == null)
throw new InternalError("Enclosing method not found");
return matching;
मेरा कहना यह है कि वैकल्पिक को कार्यात्मक प्रोग्रामिंग का समर्थन करने के लिए लिखा गया था , जिसे उसी समय जावा में जोड़ा गया था। (उदाहरण ब्रायन गोएत्ज़ द्वारा एक ब्लॉग के सौजन्य से आया है । एक बेहतर उदाहरण orElse()
विधि का उपयोग कर सकता है , क्योंकि यह कोड वैसे भी एक अपवाद को फेंक देगा, लेकिन आपको चित्र मिल जाएगा।)
लेकिन अब, लोग एक बहुत अलग कारण के लिए वैकल्पिक का उपयोग कर रहे हैं। वे इसका उपयोग भाषा डिजाइन की खामियों को दूर करने के लिए कर रहे हैं। दोष यह है: यह निर्दिष्ट करने का कोई तरीका नहीं है कि एपीआई के कौन से पैरामीटर और रिटर्न मान शून्य हैं। यह javadocs में उल्लेख किया जा सकता है, लेकिन अधिकांश डेवलपर्स अपने कोड के लिए javadocs भी नहीं लिखते हैं, और कई नहीं लिखते कि वे javadocs की जाँच करेंगे। तो यह बहुत सारे कोड की ओर जाता है जो हमेशा उपयोग करने से पहले अशक्त मूल्यों की जांच करता है, भले ही वे अक्सर शून्य नहीं हो सकते क्योंकि वे कॉल स्टैक तक नौ या दस बार पहले से ही मान्य थे।
मुझे लगता है कि इस दोष को हल करने के लिए एक वास्तविक प्यास थी, क्योंकि नए वैकल्पिक वर्ग को देखने वाले बहुत से लोगों ने इसका उद्देश्य एपीआई में स्पष्टता जोड़ना था। यही कारण है कि लोग सवाल पूछते हैं "क्या गेटर्स को ऑप्शनल रिटर्न चाहिए?" नहीं, वे शायद तब तक नहीं करना चाहिए, जब तक कि आप पाने वाले को कार्यात्मक प्रोग्रामिंग में उपयोग करने की उम्मीद नहीं करते हैं, जो बहुत संभावना नहीं है। वास्तव में, यदि आप देखते हैं कि जावा एपीआई में वैकल्पिक का उपयोग कहां किया जाता है, तो यह मुख्य रूप से स्ट्रीम कक्षाओं में है, जो कार्यात्मक प्रोग्रामिंग का मूल है। (मैंने बहुत अच्छी तरह से जाँच नहीं की है, लेकिन स्ट्रीम कक्षाएं केवल वही जगह हो सकती हैं जिसका वे उपयोग करते हैं।)
यदि आप एक कार्यात्मक कोड में बिट्टर का उपयोग करने की योजना बनाते हैं, तो मानक गेट्टर और वैकल्पिक रिटर्न करने वाले दूसरे के लिए एक अच्छा विचार हो सकता है।
ओह, और यदि आपको अपनी कक्षा को क्रमबद्ध करने की आवश्यकता है, तो आपको बिल्कुल वैकल्पिक का उपयोग नहीं करना चाहिए।
एपीआई दोष के लिए वैकल्पिक एक बहुत बुरा समाधान है क्योंकि क) वे बहुत ही क्रियात्मक हैं, और बी) वे पहली बार में उस समस्या को हल करने के लिए कभी नहीं थे।
API दोष का एक बेहतर समाधान Nullness Checker है । यह एक एनोटेशन प्रोसेसर है जो आपको यह निर्दिष्ट करने देता है कि कौन से पैरामीटर और रिटर्न वैल्यू उन्हें @ एनबल के साथ एनोटेट करके शून्य करने की अनुमति दी गई है। इस तरह, संकलक कोड को स्कैन कर सकता है और यह पता लगा सकता है कि क्या वास्तव में अशक्त होने वाले मूल्य को ऐसे मान में पारित किया जा सकता है जहां शून्य की अनुमति नहीं है। डिफ़ॉल्ट रूप से, यह मानता है कि कुछ भी अशक्त होने की अनुमति नहीं है जब तक कि इसे एनोटेट नहीं किया जाता है। इस तरह, आपको अशक्त मूल्यों के बारे में चिंता करने की ज़रूरत नहीं है। एक पैरामीटर के लिए एक शून्य मान पास करने से कंपाइलर त्रुटि होगी। नल के लिए एक वस्तु का परीक्षण करना जो शून्य नहीं हो सकता है एक संकलक चेतावनी का उत्पादन करता है। इसका प्रभाव NullPointerException को रनटाइम त्रुटि से संकलन-समय त्रुटि में बदलना है।
इससे सब कुछ बदल जाता है।
अपने गेटर्स के लिए, वैकल्पिक का उपयोग न करें। और अपनी कक्षाओं को डिजाइन करने का प्रयास करें ताकि कोई भी सदस्य संभवतः अशक्त न हो सके। और हो सकता है कि अपने प्रोजेक्ट में Nullness Checker को जोड़ने और अपने गेटर्स और सेटर पैरामीटर @Nullable की घोषणा करें यदि उन्हें इसकी आवश्यकता है। मैंने केवल नई परियोजनाओं के साथ ऐसा किया है। यह संभवत: अशक्त के लिए बहुत सारे सुपरफ्लस परीक्षणों के साथ लिखी गई मौजूदा परियोजनाओं में बहुत अधिक चेतावनी देता है, इसलिए यह पुराना करना कठिन हो सकता है। लेकिन यह बहुत सारे कीड़े भी पकड़ेगा। मुझे यह पसंद है। मेरा कोड इसकी वजह से बहुत साफ और अधिक विश्वसनीय है।
(इसमें एक नई भाषा भी है जो इसे संबोधित करती है। कोटलिन, जो जावा बाइट कोड को संकलित करता है, आपको यह निर्दिष्ट करने की अनुमति देता है कि जब आप इसे घोषित करते हैं तो कोई वस्तु अशक्त हो सकती है। यह एक क्लीनर दृष्टिकोण है।)
मूल पद के लिए परिशिष्ट (संस्करण 2)
इसे बहुत अधिक विचार देने के बाद, मैं अनिच्छा से इस निष्कर्ष पर पहुंचा हूं कि यह एक शर्त पर वैकल्पिक वापस करने के लिए स्वीकार्य है: जो मान लिया गया है वह वास्तव में अशक्त हो सकता है। मैंने बहुत से कोड देखे हैं, जहाँ लोग नियमित रूप से गेटर्स से वैकल्पिक रूप से वापसी करते हैं जो संभवतः अशक्त नहीं हो सकते। मैं इसे एक बहुत ही खराब कोडिंग अभ्यास के रूप में देखता हूं जो केवल कोड में जटिलता जोड़ता है, जिससे बग की संभावना अधिक होती है। लेकिन जब लौटा मूल्य वास्तव में अशक्त हो सकता है, तो आगे बढ़ें और इसे एक वैकल्पिक के अंदर लपेटें।
ध्यान रखें कि कार्यात्मक प्रोग्रामिंग के लिए तैयार किए गए तरीके, और जिसके लिए फ़ंक्शन संदर्भ की आवश्यकता होती है, (और) को दो रूपों में लिखा जाना चाहिए, जिनमें से एक वैकल्पिक का उपयोग करता है। उदाहरण के लिए, Optional.map()
और Optional.flatMap()
दोनों फ़ंक्शन संदर्भ लेते हैं। पहला एक साधारण गटर का संदर्भ लेता है, और दूसरा वह लेता है जो वैकल्पिक लौटाता है। तो आप किसी को भी एक वैकल्पिक रिटर्न देकर एहसान नहीं कर रहे हैं जहाँ मूल्य शून्य नहीं हो सकता है।
यह सब कहने के बाद, मैं अभी भी अशक्तता से निपटने के लिए Nullness Checker द्वारा उपयोग किए जाने वाले दृष्टिकोण को देखता हूं , क्योंकि वे NullPointerException को रन टाइम बग से संकलित करने के लिए समय त्रुटियों को संकलित करते हैं।