वैकल्पिक के लिए उपयोग करता है


271

जावा 8 का उपयोग अब 6+ महीने से कर रहा है, मैं नए एपीआई परिवर्तनों से बहुत खुश हूं। एक क्षेत्र जिसका मुझे अभी भी भरोसा नहीं है कि कब उपयोग करना है Optional। मुझे लगता है कि हर जगह इसका उपयोग करने के इच्छुक लोगों के बीच झूलना संभव है null, और कहीं भी नहीं।

ऐसा लगता है कि जब मैं इसका इस्तेमाल कर सकता हूं तो बहुत सारी स्थितियां बन सकती हैं, और मुझे यकीन नहीं है कि यह लाभ (पठनीयता / अशक्त सुरक्षा) जोड़ता है या सिर्फ अतिरिक्त उपरि का कारण बनता है।

इसलिए, मेरे कुछ उदाहरण हैं, और मुझे इस बात पर दिलचस्पी होगी कि क्या Optionalलाभकारी है या नहीं।

1 - जब विधि वापस आ सकती है तो एक सार्वजनिक विधि वापसी प्रकार के रूप में null:

public Optional<Foo> findFoo(String id);

2 - जब पैरामीटर हो सकता है एक विधि पैरामीटर के रूप में null:

public Foo doSomething(String id, Optional<Bar> barOptional);

3 - एक सेम के वैकल्पिक सदस्य के रूप में:

public class Book {

  private List<Pages> pages;
  private Optional<Index> index;

}

4 - में Collections:

सामान्य तौर पर मुझे नहीं लगता:

List<Optional<Foo>>

कुछ भी जोड़ता है - विशेष रूप से चूंकि कोई मानों आदि filter()को हटाने के लिए उपयोग कर सकता है null, लेकिन क्या Optionalसंग्रह में कोई अच्छा उपयोग है ?

जो भी केस छूटे हैं?


2
एक मामला मुझे उपयोगी लगता है, उदाहरण के लिए, यदि आपके पास एक प्रतिस्थापन मानचित्र है। उदाहरण के लिए Map<Character, String>। अगर कोई प्रतिस्थापन नहीं है तो मैं इसका उपयोग कर सकता हूं Optional.ofNullable(map.get(c)).orElse(String.valueOf(c)):। यह भी ध्यान रखें कि वैकल्पिक अमरूद चोरी हो गया था और इसमें बहुत अच्छा सिंटैक्स है:Optional.fromNullable(map.get(c)).or(String.valueOf(c));
'10

3
इसके अलावा, संग्रह में, अच्छी तरह से, वहाँ शून्य मूल्यों की अनुमति नहीं संग्रह कर रहे हैं! वैकल्पिक बिल यहाँ में फिट बैठता है। और आप कर सकते हैं .filter(Optional::absent)"शून्य मान" बाहर
fge

2
@ यदि सभी निष्पक्षता में, मुझे लगता है कि वैकल्पिक की अवधारणा वास्तव में एफपी से उपजी है।
VH-NZZ

2
@ अगर वह बेहतर के साथ व्यक्त नहीं है getOrDefault()?
जिम गैरिसन

जवाबों:


206

एक मुख्य Optionalमूल्य एक रिटर्न वैल्यू की अनुपस्थिति को इंगित करने के लिए एक मान लौटाने वाले फ़ंक्शन के लिए एक साधन प्रदान करना है। इस चर्चा को देखें । यह कॉल करने वाले को धाराप्रवाह विधि कॉल की एक श्रृंखला जारी रखने की अनुमति देता है।

यह सबसे नज़दीकी मैच ओपी के प्रश्न में केस # 1 का उपयोग करता है। हालांकि, मूल्य का अभाव अशक्त की तुलना में अधिक सटीक सूत्रीकरण है क्योंकि कुछ IntStream.findFirstभी कभी अशक्त नहीं लौट सकता है।

उपयोग केस # 2 के लिए , एक विधि के लिए एक वैकल्पिक तर्क पारित करना, यह काम करने के लिए बनाया जा सकता है, लेकिन यह बल्कि अनाड़ी है। मान लीजिए कि आपके पास एक विधि है जो एक स्ट्रिंग लेती है जिसके बाद एक वैकल्पिक दूसरी स्ट्रिंग होती है। Optionalदूसरे arg के रूप में स्वीकार करने से कोड इस प्रकार होगा:

foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());

यहां तक ​​कि शून्य को स्वीकार करना भी अच्छा है:

foo("bar", "baz");
foo("bar", null);

संभवतः सबसे अच्छा एक अतिभारित तरीका है जो एक एकल स्ट्रिंग तर्क को स्वीकार करता है और दूसरे के लिए एक डिफ़ॉल्ट प्रदान करता है:

foo("bar", "baz");
foo("bar");

इसकी सीमाएँ हैं, लेकिन यह ऊपर के दोनों की तुलना में बहुत अच्छा है।

# 3 और # 4 मामलों का उपयोग करें , Optionalएक वर्ग क्षेत्र या डेटा संरचना में होने के कारण , एपीआई का दुरुपयोग माना जाता है। सबसे पहले, यह मुख्य डिजाइन लक्ष्य के खिलाफ जाता है Optionalजैसा कि शीर्ष पर कहा गया है। दूसरा, इसका कोई मूल्य नहीं है।

एक मान के अभाव से निपटने के तीन तरीके हैं Optional: एक स्थानापन्न मूल्य प्रदान करने के लिए, एक विकल्प मूल्य प्रदान करने के लिए एक फ़ंक्शन को कॉल करने के लिए, या एक अपवाद फेंकने के लिए। यदि आप किसी फ़ील्ड में स्टोर कर रहे हैं, तो आप इसे आरंभीकरण या असाइनमेंट समय पर करेंगे। यदि आप एक सूची में मूल्यों को जोड़ रहे हैं, तो जैसा कि ओपी ने उल्लेख किया है, आपके पास केवल मूल्य नहीं जोड़ने का अतिरिक्त विकल्प है, जिससे अनुपस्थित मूल्यों को "समतल" किया जा सकता है।

मुझे यकीन है कि कोई व्यक्ति कुछ वंचित मामलों के साथ आ सकता है, जहां वे वास्तव Optionalमें एक क्षेत्र या संग्रह में स्टोर करना चाहते हैं , लेकिन सामान्य तौर पर, ऐसा करने से बचना सबसे अच्छा है।


46
मैं # 3 से असहमत हूं। यह Optionalएक क्षेत्र के रूप में उपयोगी हो सकता है जब चीजों को किया जाना है या किसी मूल्य की उपस्थिति या अनुपस्थिति पर किया जाना है।
Glglgl

15
मैं यह नहीं देखता कि if(foo == null)आंतरिक रूप से फील्ड को स्टोर करने से बेहतर क्यों होगा optional। और मैं यह नहीं देखता कि स्पष्ट रूप से getOptionalFoo()आंतरिक रूप से कॉल करना क्षेत्र के रूप में भंडारण करने से बेहतर है Optional। इसके अलावा, यदि एक क्षेत्र हो सकता है nullऔर एक क्षेत्र नहीं हो सकता है null, तो संकलक को उन्हें बनाने Optionalया न करने के लिए संवाद क्यों नहीं करना चाहिए Optional
मोग्रानालोल

27
@StuartMarks, यह उन सभी चीजों में से एक है जो मुझे सभी Optional<>विशेषज्ञों से सुनते समय मुझे परेशान करती हैं: " Optional<>एक क्षेत्र में स्टोर न करें "। मैं वास्तव में इस सिफारिश के बिंदु को समझने की कोशिश कर रहा हूं। एक डोम ट्री पर विचार करें जहां एक नोड में माता-पिता हो सकते हैं या नहीं। यह उपयोग के मामले में लगता है Node.getParent()कि वापस आ जाएगा Optional<Node>। क्या मुझे वास्तव में nullहर बार एक स्टोर करने और परिणाम को लपेटने की उम्मीद है ? क्यों? यह अतिरिक्त अक्षमता मुझे क्या खरीदती है, जो मेरे कोड को बदसूरत बनाने के अलावा है?
गैरेट विल्सन

7
@GarretWilson दूसरी ओर, मान लीजिए कि आपके पास है Optional<Node> getParent() { return Optional.ofNullable(parent); }। यह महंगा लग रहा है क्योंकि यह Optionalहर बार आवंटित करता है! लेकिन अगर कॉलर इसे तुरंत हटा देता है, तो वस्तु अत्यंत अल्पकालिक होती है और इसे कभी भी एडन स्पेस से बाहर नहीं किया जाता है। यह संभवत: जेआईटी के भागने के विश्लेषण द्वारा भी समाप्त किया जा सकता है। लब्बोलुआब यह है कि यह हमेशा की तरह "निर्भर करता है" होता है, लेकिन Optionalखेतों में उपयोग करने से मेमोरी का उपयोग होता है और डेटा स्ट्रक्चर ट्रैवर्सल को धीमा कर देता है। और अंत में मुझे लगता है कि यह कोड अप कर देता है, लेकिन यह स्वाद का मामला है।
स्टुअर्ट मार्क्स

6
@GarretWilson तो क्या आपने उसके लिए एक ब्लॉग लिखा है? मुझे उस पर दिलचस्पी होगी :)
akhil_mittal

78

मुझे खेल के लिए देर हो रही है लेकिन इसके लायक क्या है, मैं अपने 2 सेंट जोड़ना चाहता हूं। वे डिजाइन लक्ष्य केOptional खिलाफ जाते हैं , जिसे स्टुअर्ट मार्क्स के जवाब से अच्छी तरह से संक्षेप में प्रस्तुत किया गया है , लेकिन मैं अभी भी उनकी वैधता (स्पष्ट रूप से) के बारे में आश्वस्त हूं।

वैकल्पिक हर जगह का उपयोग करें

सामान्य रूप में

मैंने उपयोग करने के बारे मेंOptional एक पूरी ब्लॉग पोस्ट लिखी है, लेकिन यह मूल रूप से इस पर आती है:

  • जहाँ संभव हो, वैकल्पिकता से बचने के लिए अपनी कक्षाओं को डिज़ाइन करें
  • शेष सभी मामलों में, Optionalइसके बजाय डिफ़ॉल्ट का उपयोग करना चाहिएnull
  • संभवतः इसके लिए अपवाद बनाएं:
    • स्थानीय चर
    • निजी विधियों में मान और तर्क लौटाएं
    • प्रदर्शन महत्वपूर्ण कोड ब्लॉक (कोई अनुमान नहीं है, एक प्रोफाइलर का उपयोग करें)

पहले दो अपवाद रैपिंग और अलिखित संदर्भों के कथित ओवरहेड को कम कर सकते हैं Optional। उन्हें इस तरह चुना जाता है कि एक अशक्त कानूनी रूप से कभी भी एक उदाहरण से दूसरे में एक सीमा पार नहीं कर सकता है।

ध्यान दें कि यह लगभग कभी भी Optionalसंग्रह में एस की अनुमति नहीं देगा जो लगभग उतना ही बुरा है जितना कि nullएस। बस यह मत करो। ;)

अपने सवालों के बारे में

  1. हाँ।
  2. यदि ओवरलोडिंग कोई विकल्प नहीं है, तो हाँ।
  3. यदि अन्य दृष्टिकोण (उपवर्ग, सजाने, ...) कोई विकल्प नहीं हैं, हाँ।
  4. कृपया नहीं!

लाभ

ऐसा करने nullसे आपके कोड आधार में s की उपस्थिति कम हो जाती है , हालांकि यह उन्हें नहीं मिटाता है। लेकिन वह मुख्य बिंदु भी नहीं है। अन्य महत्वपूर्ण लाभ हैं:

आशय स्पष्ट करता है

Optionalस्पष्ट रूप से उपयोग करने से पता चलता है कि चर, ठीक है, वैकल्पिक है। आपके कोड के किसी भी पाठक या आपके एपीआई के उपभोक्ता को इस तथ्य के साथ सिर पर पीटा जाएगा कि वहाँ कुछ भी नहीं हो सकता है और मूल्य तक पहुंचने से पहले एक चेक आवश्यक है।

अनिश्चितता को दूर करता है

बिना घटना Optionalके अर्थ nullस्पष्ट नहीं है। यह Map.getएक लापता (विफल) या प्रारंभिक प्रारंभ की तरह एक राज्य (देखें ) या एक कार्यान्वयन त्रुटि का कानूनी प्रतिनिधित्व हो सकता है।

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

अधिक अशक्त चेक

अब और कुछ भी नहीं हो सकता है null, इसे हर जगह लागू किया जा सकता है। एनोटेशन, दावे या सादे चेक के साथ, आपको इस बारे में कभी नहीं सोचना चाहिए कि क्या यह तर्क या वह रिटर्न प्रकार अशक्त हो सकता है। यह नहीं कर सकता!

नुकसान

बेशक, कोई चांदी की गोली नहीं है ...

प्रदर्शन

एक अतिरिक्त उदाहरण में रैपिंग मान (विशेष रूप से आदिम) प्रदर्शन को नीचा दिखा सकते हैं। तंग छोरों में यह ध्यान देने योग्य या इससे भी बदतर हो सकता है।

ध्यान दें कि कंपाइलर Optionalएस के अल्पकालिक जीवनकाल के लिए अतिरिक्त संदर्भ को दरकिनार करने में सक्षम हो सकता है । जावा में 10 प्रकार के मान दंड को कम कर सकते हैं या हटा सकते हैं।

क्रमबद्धता

Optionalक्रमबद्ध नहीं है, लेकिन एक वैकल्पिक हल अत्यधिक जटिल नहीं है।

निश्चरता

जावा में जेनेरिक प्रकारों के आक्रमण के कारण, कुछ निश्चित ऑपरेशन बोझिल हो जाते हैं जब वास्तविक मूल्य प्रकार को जेनेरिक प्रकार के तर्क में धकेल दिया जाता है। एक उदाहरण यहां दिया गया है ("पैरामीट्रिक पॉलीमॉर्फिज्म" देखें)


एक और नुकसान (या सीमा) यह है कि आप वैकल्पिक (एक्सएक्सएक्स) उदाहरणों को सॉर्ट नहीं कर सकते हैं, हालांकि ओरेकल ने स्पष्ट रूप से प्रतिबंध को स्पष्ट रूप से लगाया है। मुझे इन वर्गों के उपलब्ध होने की बुद्धिमत्ता पर संदेह है जहाँ उन्हें केवल विशिष्ट परिस्थितियों में उपयोग किया जाना चाहिए, और यह मानकर कि डेवलपर सही काम करेंगे। एक समस्या का समाधान एक और कारण हो सकता है। हो सकता है कि डेवलपर को "अवांछनीय" तरीके (जैसे विधि मापदंडों के रूप में, संग्रह में, कंस्ट्रक्टर आदि में) का उपयोग करते समय डेवलपर की सहायता करने के लिए कंपाइलर चेतावनी हो, अगर वास्तव में इरादा उपयोग नहीं है?
स्कोमीसा

संग्रह में 4, वैकल्पिक के बारे में: यह वास्तव में कभी-कभी वैकल्पिक को स्टोर करने के लिए उपयोगी होता है List। यह मामला है जब यह महत्वपूर्ण है कि एक निश्चित तत्व एक निश्चित सूचकांक पर स्थित है, लेकिन तत्व मौजूद हो सकता है या नहीं। यह स्पष्ट रूप से एक List<Optional<T>>प्रकार से संप्रेषित होता है । यदि दूसरी ओर यह केवल महत्वपूर्ण है कि कौन सी वस्तुएं किसी न किसी संग्रह के सदस्य हैं तो कोई बात नहीं है।
Lii

3
मुझे लगता है कि उपयोग-केस # 2 अभी भी बहुत संदिग्ध है। एक Optionalविधि में पारित किया जा सकता है null। तो आपने क्या हासिल किया है? अब आपके पास बनाने के लिए दो चेक हैं। देखें stackoverflow.com/a/31923042/650176
डेविड वी

2
@ डेविड ने मेरे द्वारा दिए गए फायदों की सूची को देखा - वे सभी उस मामले में भी लागू होते हैं। इसके अलावा, यदि आप सभी पर चलते हैं Optional(जो कि यदि आप इसे तर्क के रूप में पारित करना चाहते हैं तो मामला होना चाहिए) nullकभी भी कानूनी मूल्य नहीं है। तो एक स्पष्ट पैरामीटर के साथ एक विधि को कॉल करना स्पष्ट nullरूप से एक गलती है।
निकोलई

28

व्यक्तिगत रूप से, मैं उपयोग करने के लिए IntelliJ के कोड निरीक्षण उपकरण का उपयोग करना पसंद करता हूं @NotNullऔर @Nullableजांच करता हूं क्योंकि ये बड़े पैमाने पर संकलन समय (कुछ रनटाइम चेक हो सकते हैं) यह कोड पठनीयता और रनटाइम प्रदर्शन के मामले में कम ओवरहेड है। यह वैकल्पिक का उपयोग करने के रूप में कठोर नहीं है, हालांकि कठोरता की इस कमी को सभ्य इकाई परीक्षणों द्वारा समर्थित किया जाना चाहिए।

public @Nullable Foo findFoo(@NotNull String id);

public @NotNull Foo doSomething(@NotNull String id, @Nullable Bar barOptional);

public class Book {

  private List<Pages> pages;
  private @Nullable Index index;

}

List<@Nullable Foo> list = ..

यह जावा 5 के साथ काम करता है और मूल्यों को लपेटने और अनचाहे करने की आवश्यकता नहीं है। (या आवरण वस्तुएं बनाएं)


7
उह, क्या ये आईडिया एनोटेशन हैं? मैं JSR 305 को @Nonnullव्यक्तिगत रूप से पसंद करता
हूं

@ यदि इस संबंध में मानकों की कमी है, लेकिन मेरा मानना ​​है कि उपकरण आम तौर पर विन्यास योग्य हैं और आपको समाप्त नहीं होना है@Nonnull @NotNull etc
पीटर लॉरी

4
हाँ वह सच है; आईडीईए (13.x) तीन अलग-अलग विकल्प देता है ... मेह, मैं हमेशा जेएसआर 305 का उपयोग कर समाप्त करता हूं
फेज

3
मुझे पता है कि यह पुराना है, लेकिन एनोटेशन और टूल्स के बारे में चर्चा stackoverflow.com/questions/35892063/… के लिंक की हकदार है, जो btw विशेष रूप से जावा 8 के मामले को संबोधित करता है।
Stephan Herrmann

25

मुझे लगता है कि अमरूद वैकल्पिक और उनके विकी पृष्ठ इसे काफी अच्छी तरह से कहते हैं:

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

यह विशेष रूप से प्रासंगिक है जब आप उन मूल्यों को वापस कर रहे हैं जो "वर्तमान" हो सकते हैं या नहीं हो सकते हैं। आप (और अन्य) यह भूल जाते हैं कि अन्य.method (a, b) एक शून्य मान लौटा सकते हैं, जबकि आप यह भूल सकते हैं कि जब आप दूसरे.method को लागू कर रहे हैं तो यह शून्य हो सकता है। रिटर्निंग ऑप्शनल ने कॉल करने वालों के लिए उस मामले को भूलना असंभव बना दिया है, क्योंकि उन्हें अपने कोड को संकलित करने के लिए ऑब्जेक्ट को खुद को अनफ्रैप करना पड़ता है। - (स्रोत: अमरूद विकी - अशक्त का उपयोग करना और बचना - क्या बात है? )

Optionalकुछ ओवरहेड जोड़ता है, लेकिन मुझे लगता है कि इसका स्पष्ट लाभ यह स्पष्ट करना है कि एक वस्तु अनुपस्थित हो सकती है और यह लागू करता है कि प्रोग्रामर स्थिति को संभालते हैं। यह रोकता है कि कोई प्रिय != nullजाँच भूल जाता है ।

2 का उदाहरण लेते हुए , मुझे लगता है कि यह लिखना अधिक स्पष्ट कोड है:

if(soundcard.isPresent()){
  System.out.println(soundcard.get());
}

से

if(soundcard != null){
  System.out.println(soundcard);
}

मेरे लिए, Optionalबेहतर इस तथ्य को पकड़ता है कि कोई साउंडकार्ड मौजूद नहीं है।

आपके बिंदुओं के बारे में मेरा 2 your:

  1. public Optional<Foo> findFoo(String id);- मैं इस बारे में निश्चित नहीं हूँ। शायद मैं वापस आ जाऊंगा Result<Foo>जो खाली हो सकता है या इसमें शामिल हो सकता है Foo। यह एक समान अवधारणा है, लेकिन वास्तव में नहीं है Optional
  2. public Foo doSomething(String id, Optional<Bar> barOptional);- मैं पीटर लॉन के जवाब में @Nullable और फाइंडबग्स चेक पसंद करूंगा - यह चर्चा भी देखें ।
  3. आपकी पुस्तक उदाहरण - मुझे यकीन नहीं है कि अगर मैं आंतरिक रूप से वैकल्पिक का उपयोग करूंगा, तो यह जटिलता पर निर्भर हो सकता है। किसी पुस्तक के "एपीआई" के लिए, मैं Optional<Index> getIndex()स्पष्ट रूप से इंगित करने के लिए एक का उपयोग करता हूं कि पुस्तक में कोई सूचकांक नहीं हो सकता है।
  4. मैं इसे संग्रह में उपयोग नहीं करूंगा, बल्कि संग्रह में अशक्त मूल्यों की अनुमति नहीं दूंगा

सामान्य तौर पर, मैं nullएस के आसपास से गुजरने को कम करने की कोशिश करूंगा । (एक बार जला दिया गया ...) मुझे लगता है कि यह उचित सार खोजने के लिए और साथी प्रोग्रामर को इंगित करने के लिए लायक है जो वास्तव में एक निश्चित वापसी मूल्य का प्रतिनिधित्व करता है।


15
आप लिखेंगे soundcard.ifPresent(System.out::println)। कॉलिंग isPresentशब्दार्थ रूप से जाँच के लिए समान है null
एक बेहतर ओलिवर

मेरे लिए मुद्दा यह है कि वैकल्पिक प्रकार वाली चीजें अभी भी अशक्त हो सकती हैं। तो वास्तव में पूरी तरह से सुरक्षित होने के लिए आपको कुछ करना होगा if(soundcard != null && soundcard.isPresent())। हालांकि एक एपीआई करना जो एक वैकल्पिक लौटाता है और अशक्त भी लौट सकता है, मुझे आशा है कि कोई भी कभी भी ऐसा नहीं करेगा।
साइमन बॉमगार्ड-वेलैंडर

"यह आपको अनुपस्थित मामले के बारे में सक्रिय रूप से सोचने के लिए मजबूर करता है यदि आप चाहते हैं कि आपका कार्यक्रम सभी को संकलित करें, क्योंकि आपको वैकल्पिक रूप से उस मामले को खोलना है और उस मामले को संबोधित करना है।" मुझे वास्तव में यकीन नहीं है कि यह कैसे बल देता है, हालांकि मैं जावा में काम नहीं करता हूं। क्या आप समझा सकते हैं कि जावा आपको अनचेक करने और चेक करने के लिए मजबूर करने के लिए क्या करता है?
क्रश करें

15

से ओरेकल ट्यूटोरियल :

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


3
एपीआई विधि के वापसी के हिस्से के लिए ही सही? वैकल्पिकों को टाइप-एरासुर के कारण मापदंडों के रूप में उपयोग नहीं किया जाना चाहिए? कभी-कभी मैं एक वैकल्पिक रूप से एक विधि में आंतरिक रूप से उपयोग करता हूं, एक अशक्त पैरामीटर से या एक क्षेत्र के रूप में एक नल निर्माता पैरामीटर से प्रारंभ होता है ... फिर भी यह पता लगाने की कोशिश कर रहा है कि क्या यह अशक्त छोड़ने की तुलना में अधिक उपयोगी है - किसी को भी कोई विचार है?
ycomp

@ycomp आप इस या उस प्रश्न में उन मामलों के बारे में काफी जानकारी पा सकते हैं । उन सवालों के जवाब बहुत अधिक बताए गए हैं जो अन्य मामलों के बारे में पूछे गए थे। अधिक जानकारी के लिए, अधिक ब्राउज़ करें या अपना स्वयं का प्रश्न पूछें, क्योंकि शायद आपको यहां अधिक ध्यान नहीं मिलेगा। ; )
ctomek 18

8

1 - एक सार्वजनिक विधि वापसी प्रकार के रूप में जब विधि शून्य हो सकती है:

यहाँ एक अच्छा लेख है जो usecase # 1 की उपयोगिता दर्शाता है। वहाँ इस कोड

...
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            String isocode = country.getIsocode();
            isocode = isocode.toUpperCase();
        }
    }
}
...

में तब्दील हो गया है

String result = Optional.ofNullable(user)
  .flatMap(User::getAddress)
  .flatMap(Address::getCountry)
  .map(Country::getIsocode)
  .orElse("default");

संबंधित गेटर तरीकों के रिटर्न वैल्यू के रूप में वैकल्पिक का उपयोग करके ।


2

यहां ... टेस्ट के लिए एक दिलचस्प उपयोग (मेरा मानना ​​है) है।

मैं अपनी एक परियोजना का भारी परीक्षण करने का इरादा रखता हूं और इसलिए मैं जोर देता हूं; केवल वही चीजें हैं जो मुझे सत्यापित करनी हैं और अन्य जिन्हें मैं नहीं करता हूं।

इसलिए मैं चीजों का निर्माण करता हूं और उन्हें सत्यापित करने के लिए एक मुखर का उपयोग करता हूं, जैसे:

public final class NodeDescriptor<V>
{
    private final Optional<String> label;
    private final List<NodeDescriptor<V>> children;

    private NodeDescriptor(final Builder<V> builder)
    {
        label = Optional.fromNullable(builder.label);
        final ImmutableList.Builder<NodeDescriptor<V>> listBuilder
            = ImmutableList.builder();
        for (final Builder<V> element: builder.children)
            listBuilder.add(element.build());
        children = listBuilder.build();
    }

    public static <E> Builder<E> newBuilder()
    {
        return new Builder<E>();
    }

    public void verify(@Nonnull final Node<V> node)
    {
        final NodeAssert<V> nodeAssert = new NodeAssert<V>(node);
        nodeAssert.hasLabel(label);
    }

    public static final class Builder<V>
    {
        private String label;
        private final List<Builder<V>> children = Lists.newArrayList();

        private Builder()
        {
        }

        public Builder<V> withLabel(@Nonnull final String label)
        {
            this.label = Preconditions.checkNotNull(label);
            return this;
        }

        public Builder<V> withChildNode(@Nonnull final Builder<V> child)
        {
            Preconditions.checkNotNull(child);
            children.add(child);
            return this;
        }

        public NodeDescriptor<V> build()
        {
            return new NodeDescriptor<V>(this);
        }
    }
}

NodeAssert वर्ग में, मैं यह करता हूं:

public final class NodeAssert<V>
    extends AbstractAssert<NodeAssert<V>, Node<V>>
{
    NodeAssert(final Node<V> actual)
    {
        super(Preconditions.checkNotNull(actual), NodeAssert.class);
    }

    private NodeAssert<V> hasLabel(final String label)
    {
        final String thisLabel = actual.getLabel();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is null! I didn't expect it to be"
        ).isNotNull();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is not what was expected!\n"
            + "Expected: '%s'\nActual  : '%s'\n", label, thisLabel
        ).isEqualTo(label);
        return this;
    }

    NodeAssert<V> hasLabel(@Nonnull final Optional<String> label)
    {
        return label.isPresent() ? hasLabel(label.get()) : this;
    }
}

अगर मैं लेबल की जाँच करना चाहता हूँ तो मुखर वास्तव में केवल ट्रिगर होता है!


2

Optionalकक्षा आपको nullएक बेहतर विकल्प प्रदान करने और प्रदान करने से बचती है :

  • यह डेवलपर को बिना पढ़े से बचने के लिए उपस्थिति के लिए जाँच करने के लिए प्रोत्साहित करता है NullPointerException

  • एपीआई बेहतर दस्तावेज बन जाता है क्योंकि यह देखना संभव है, जहां उन मूल्यों की अपेक्षा करना है जो अनुपस्थित हो सकते हैं।

Optionalऑब्जेक्ट के साथ आगे के काम के लिए सुविधाजनक एपीआई प्रदान करता है isPresent():; get(); orElse(); orElseGet(); orElseThrow(); map(); filter(); flatmap()

इसके अलावा, कई ढांचे सक्रिय रूप से इस डेटा प्रकार का उपयोग करते हैं और इसे अपने एपीआई से वापस करते हैं।


2

जावा में, बस उनका उपयोग न करें जब तक कि आप कार्यात्मक प्रोग्रामिंग के आदी नहीं हैं।

उनके पास विधि तर्कों के रूप में कोई जगह नहीं है (मैं किसी को प्रॉमिस करता हूं कि एक दिन आप एक शून्य वैकल्पिक पास करेंगे, न कि केवल एक वैकल्पिक जो खाली है)।

वे वापसी मूल्यों के लिए समझ में आते हैं, लेकिन वे व्यवहार-निर्माण श्रृंखला को जारी रखने के लिए ग्राहक वर्ग को आमंत्रित करते हैं।

एफपी और जंजीरों का जावा जैसी अनिवार्य भाषा में बहुत कम स्थान है क्योंकि यह केवल पढ़ने के लिए नहीं, बल्कि डिबग करने के लिए बहुत कठिन बनाता है। जब आप लाइन पर कदम रखते हैं, तो आप राज्य और कार्यक्रम का इरादा नहीं जान सकते हैं; आपको यह पता लगाने के लिए कदम रखना होगा (कोड में जो अक्सर आपका नहीं होता है और स्टेप फिल्टर के बावजूद कई स्टैक फ्रेम गहरे होते हैं) और आपको यह सुनिश्चित करने के लिए बहुत सारे ब्रेकप्वाइंट जोड़ने होंगे कि यह आपके द्वारा जोड़े गए कोड / लैम्ब्डा में बंद हो सकता है। इसके बजाय बस अगर चलना / और / तुच्छ लाइनों को बुलाओ।

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


1

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

मूल विचार यह है: मूल्य की अनुपस्थिति का मतलब यह नहीं है कि यह संभावित रूप से भविष्य में उपलब्ध है। यह findById (-1) और findById (67) के बीच अंतर है।

कॉल करने वाले के लिए वैकल्पिक की मुख्य जानकारी यह है कि वह दिए गए मूल्य पर भरोसा नहीं कर सकता है, लेकिन यह कुछ समय पर उपलब्ध हो सकता है। हो सकता है कि यह फिर से गायब हो जाए और एक बार फिर वापस आ जाए। यह एक चालू / बंद स्विच की तरह है। आपके पास प्रकाश को चालू या बंद करने का "विकल्प" है। लेकिन अगर आपके पास स्विच ऑन करने के लिए लाइट नहीं है तो आपके पास कोई विकल्प नहीं है।

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


0

लगता है Optional, तो वैकल्पिक में टाइप टी की तरह एक आदिम प्रकार है ही उपयोगी है int, long, char, आदि "असली" वर्गों के लिए, यह मेरे लिए कोई मतलब नहीं है के रूप में आप एक का उपयोग कर सकते nullमूल्य वैसे भी।

मुझे लगता है कि इसे यहां से (या इसी तरह की भाषा की अवधारणा से) लिया गया था।

Nullable<T>

C # में यह Nullable<T>बहुत पहले मूल्य प्रकार लपेटने के लिए पेश किया गया था।


2
यह अमरूद की एक ripoff है है Optionalमें तथ्य
fge

2
@ ठीक है, लेकिन जब यह C # (2005, MS.NET 2.0) में मौजूद था, तो कोई अमरूद नहीं था, मुझे लगता है। और ... कौन जानता है कि सी # ने यह कहां से लिया।
peter.petrov

3
@ एफएजी "रवाफ़ ऑफ़ गुवाज़ ऑप्शनल" इसे डालने का एक मज़ेदार तरीका है, क्योंकि गुवा लोगों ने चर्चाओं में भाग लिया, अपने अनुभव प्रदान किए और आम तौर पर इसके पक्ष में थे java.util.Optional
स्टुअर्ट मार्क्स

6
@ कोई शक नहीं जावा के एपीआई अमरूद से बहुत प्रभावित थे। मैं "ripoff" के साथ समस्या ले रहा हूं जो चोरी की तरह लग रहा है। अमरूद वालों ने जावा 8.
स्टुअर्ट मार्क्स

6
आप बात याद कर रहे हैं। अशक्त लौटने के बजाय वैकल्पिक उपयोग किया जाना है। यह संभवतः NullPointerException को फेंकने से अधिक सुरक्षित है। देखें: oracle.com/technetwork/articles/java/…
Kilizo

0

एक समान शब्दार्थ है Iterator डिजाइन पैटर्न के एक अपरिवर्तनीय उदाहरण के लिए :Optional

  • यह किसी वस्तु को संदर्भित कर भी सकता है और नहीं भी (जैसा कि इसके द्वारा दिया गया है isPresent())
  • get()अगर यह किसी वस्तु को संदर्भित करता है तो इसका उपयोग किया जा सकता है
  • लेकिन यह अनुक्रम में अगली स्थिति के लिए उन्नत नहीं हो सकता है (इसकी कोई next()विधि नहीं है)।

इसलिए Optionalउन संदर्भों में लौटने या पारित करने पर विचार करें जहां आपने पहले जावा का उपयोग करने पर विचार किया होगा Iterator


-1

जावा एसई 8 java.util.Optional नामक एक नई कक्षा का परिचय देता है,

आप रिक्त मान के साथ एक रिक्त वैकल्पिक या वैकल्पिक बना सकते हैं।

Optional<String> emptyOptional = Optional.empty(); 

और यहाँ एक गैर-शून्य मान के साथ एक वैकल्पिक है:

String valueString = new String("TEST");
Optional<String> optinalValueString = Optional.of(valueString );

कुछ करो अगर एक मूल्य मौजूद है

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

String nullString = null;
if (nullString != null) {
    System.out.println(nullString);
}

आप निम्नानुसार ifPresent () विधि का उपयोग कर सकते हैं:

Optional<String> optinalString= null;
optinalString.ifPresent(System.out::println);

package optinalTest;

import java.util.Optional;

public class OptionalTest {
    public Optional<String> getOptionalNullString() {
        return null;
//      return Optional.of("TESt");
    }

    public static void main(String[] args) {

        OptionalTest optionalTest = new OptionalTest();

        Optional<Optional<String>> optionalNullString = Optional.ofNullable(optionalTest.getOptionalNullString());

        if (optionalNullString.isPresent()) {
            System.out.println(optionalNullString.get());
        }
    }
}

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