सवाल बचना! = शून्य बयान


मैं उपयोग करता हूं object != null से बचने के लिए बहुत कुछ NullPointerException

क्या इसका कोई अच्छा विकल्प है?

उदाहरण के लिए:

if (someobject != null) {
    someobject.doCalc();
}

यह एक से बचाता है NullPointerException, जब ऑब्जेक्ट होता है तो यह अज्ञात है null या नहीं।

ध्यान दें कि स्वीकृत उत्तर पुराना हो सकता है, देखें https://stackoverflow.com/a/2386013/12943 एक और हालिया दृष्टिकोण के लिए।


3553


मूल


@ शेरविन नेल्स को प्रोत्साहित करने से कोड कम समझ में आता है और कम विश्वसनीय होता है। - Tom Hawtin - tackline
एल्विस ऑपरेटर थे प्रस्तावित लेकिन ऐसा लगता है कि यह अंदर नहीं होगा जावा 7। बहुत बुरा, ?। ?: और? [] अविश्वसनीय समय बचतकर्ता हैं। - Scott
नल का उपयोग नहीं करना यहां अन्य सुझावों से बेहतर है। अपवाद फेंको, वापस न करें या नल की अनुमति दें। बीटीडब्ल्यू - 'जोर' कीवर्ड बेकार है, क्योंकि यह डिफ़ॉल्ट रूप से अक्षम है। एक हमेशा सक्षम विफलता तंत्र का प्रयोग करें - ianpojman
यह एक कारण है कि अब मैं स्कैला का उपयोग कर रहा हूं। स्कैला में सब कुछ शून्य नहीं है। यदि आप "कुछ भी नहीं" पास करने या वापस जाने की अनुमति देना चाहते हैं, तो आपको केवल टी एलएस तर्क या वापसी प्रकार के बजाय विकल्प [टी] का उपयोग करना होगा। - Thekwasti
@thSoft वास्तव में, स्कैला भयानक Option भाषा को नियंत्रित करने या अस्वीकार करने की भाषा की अनिच्छा से टाइप किया जाता है null। मैंने हैकन्यूज़ पर इसका उल्लेख किया और नीचे गिर गया और कहा कि "कोई भी स्कैला में किसी भी तरह का उपयोग नहीं करता है"। मान लीजिए, मैं पहले से ही सहकर्मी-लिखित स्कैला में नल ढूंढ रहा हूं। हां, वे "इसे गलत कर रहे हैं" और इसके बारे में शिक्षित होना चाहिए, लेकिन तथ्य यह है कि भाषा की प्रकार प्रणाली मुझे इससे बचा लेनी चाहिए और यह नहीं है :( - Andres F.


जवाब:


यह मेरे लिए एक सामान्य आम समस्या की तरह लगता है कि मध्यवर्ती से मध्यवर्ती डेवलपर्स को किसी बिंदु पर सामना करना पड़ता है: वे या तो उन अनुबंधों पर भरोसा नहीं करते हैं जिन्हें वे भाग ले रहे हैं और रक्षात्मक रूप से नल के लिए ओवरकेक करते हैं। इसके अतिरिक्त, जब वे अपना कोड लिखते हैं, तो वे कॉलर को नल की जांच करने के लिए कुछ ऐसा इंगित करने के लिए वापस लौटने पर भरोसा करते हैं।

इसे एक और तरीके से रखने के लिए, दो उदाहरण हैं जहां शून्य जांच आती है:

  1. अनुबंध के संदर्भ में जहां शून्य एक वैध प्रतिक्रिया है; तथा

  2. जहां यह वैध प्रतिक्रिया नहीं है।

(2) आसान है। या तो उपयोग करें assert बयान (दावे) या विफलता की अनुमति (उदाहरण के लिए, शून्य सूचक अपवाद)। दावा एक अत्यधिक अंतर्निहित जावा सुविधा है जो 1.4 में जोड़ा गया था। वाक्यविन्यास है:

assert <condition>

या

assert <condition> : <object>

कहा पे <condition> एक बुलियन अभिव्यक्ति है और <object> एक वस्तु है जिसका toString() विधि का आउटपुट त्रुटि में शामिल किया जाएगा।

एक assert बयान एक फेंकता है Error (AssertionError) अगर स्थिति सच नहीं है। डिफ़ॉल्ट रूप से, जावा दावे को अनदेखा करता है। आप विकल्प पारित करके दावे को सक्षम कर सकते हैं -ea जेवीएम के लिए। आप व्यक्तिगत कक्षाओं और संकुलों के लिए दावे को सक्षम और अक्षम कर सकते हैं। इसका मतलब यह है कि आप विकास और परीक्षण करते समय दावे के साथ कोड को मान्य कर सकते हैं, और उन्हें उत्पादन वातावरण में अक्षम कर सकते हैं, हालांकि मेरा परीक्षण दावे से प्रदर्शन प्रभाव के बगल में दिखाया गया है।

इस मामले में दावे का उपयोग नहीं करना ठीक है क्योंकि कोड बस असफल हो जाएगा, अगर आप दावाों का उपयोग करते हैं तो क्या होगा। केवल अंतर यह है कि दावाों के साथ यह जल्द से जल्द, अधिक अर्थपूर्ण तरीके से और संभवतः अतिरिक्त जानकारी के साथ हो सकता है, जो आपको यह समझने में मदद कर सकता है कि ऐसा क्यों हुआ जब आप इसकी अपेक्षा नहीं कर रहे थे।

(1) थोड़ा कठिन है। यदि आपके द्वारा कॉल किए जा रहे कोड पर आपका कोई नियंत्रण नहीं है तो आप अटक गए हैं। अगर शून्य मान्य प्रतिक्रिया है, तो आपको इसकी जांच करनी होगी।

यदि यह कोड है जिसे आप नियंत्रित करते हैं, हालांकि (और यह अक्सर मामला है), तो यह एक अलग कहानी है। प्रतिक्रिया के रूप में nulls का उपयोग करने से बचें। संग्रहों को वापस करने वाले तरीकों के साथ, यह आसान है: हर समय नल की जगह खाली संग्रह (या सरणी) वापस लौटें।

गैर-संग्रह के साथ यह कठिन हो सकता है। इसे एक उदाहरण के रूप में देखें: यदि आपके पास इन इंटरफेस हैं:

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

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

एक वैकल्पिक समाधान कभी वापस शून्य नहीं करना है और इसके बजाय इसका उपयोग करना है शून्य ऑब्जेक्ट पैटर्न:

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

की तुलना करें:

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

सेवा मेरे

ParserFactory.getParser().findAction(someInput).doSomething();

जो एक बेहतर डिजाइन है क्योंकि यह अधिक संक्षिप्त कोड की ओर जाता है।

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

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

या यदि आपको लगता है कि कोशिश / पकड़ तंत्र बहुत बदसूरत है, तो कुछ भी नहीं करने के बजाय आपकी डिफ़ॉल्ट कार्रवाई को उपयोगकर्ता को फीडबैक देना चाहिए।

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}

2392



मैं DO_NOTHING कार्रवाई के लिए आपके बयान से असहमत हूं। यदि खोज क्रिया विधि को कोई क्रिया नहीं मिल रही है, तो शून्य वापस लौटना सही काम है। आपने अपने कोड में एक क्रिया "पाया" है जो वास्तव में नहीं मिला है, जो उपयोग योग्य कार्रवाई खोजने के लिए विधि के सिद्धांत का उल्लंघन करता है। - MetroidFan2002
मैं सहमत हूं कि जावा में विशेष रूप से सूचियों के साथ शून्य का उपयोग नहीं किया जाता है। अगर वे खाली की बजाय खाली सूची / सरणी / संग्रह वापस करते हैं तो बहुत से एपिस बेहतर होंगे। कई बार, शून्य का उपयोग किया जाता है जहां इसके बजाय एक अपवाद फेंक दिया जाना चाहिए। पार्सर पार्स नहीं कर सकता है तो एक अपवाद फेंक दिया जाना चाहिए। - Laplie Anderson
यहां का दूसरा उदाहरण है, आईआईआरसी, नल ऑब्जेक्ट डिज़ाइन पैटर्न। - Steven Evers
@Cshah (और MetroidFan2002)। सरल, इसे अनुबंध में डाल दें और फिर यह स्पष्ट हो जाए कि एक गैर-लौटाई गई कार्रवाई कुछ भी नहीं करेगी। यदि यह कॉलर को महत्वपूर्ण जानकारी है, तो यह पता लगाने का एक तरीका प्रदान करें कि यह एक गैर-निष्पादित कार्रवाई थी (यानी यह जांचने के लिए एक तरीका प्रदान करें कि परिणाम DO_NOTHING ऑब्जेक्ट था या नहीं)। वैकल्पिक रूप से, यदि कार्रवाई सामान्य रूप से पाई जानी चाहिए तो आपको अभी भी शून्य वापस नहीं करना चाहिए, बल्कि इसके बजाय एक अपवाद फेंकना चाहिए जो विशेष रूप से उस स्थिति को इंगित करता है - यह अभी भी बेहतर कोड में परिणाम देता है। अगर वांछित है, तो यह जांचने के लिए कि क्या कार्रवाई मौजूद है, एक अलग विधि लौटने वाला बूलियन प्रदान करें। - Kevin Brock
संक्षिप्त गुणवत्ता कोड के बराबर नहीं है। मुझे खेद है कि आप ऐसा सोचते हैं। आपका कोड उन स्थितियों को छुपाता है जहां एक त्रुटि लाभप्रद होगी। - gshauger


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

असल में, आपको मिल गया है @Nullable तथा @NotNull

आप विधि और पैरामीटर में इस तरह उपयोग कर सकते हैं:

@NotNull public static String helloWorld() {
    return "Hello World";
}

या

@Nullable public static String helloWorld() {
    return "Hello World";
}

दूसरा उदाहरण संकलित नहीं होगा (इंटेलिजे आईडीईए में)।

जब आप पहले उपयोग करते हैं helloWorld() कोड के दूसरे टुकड़े में कार्य करें:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

अब इंटेलिजे आईडीईए कंपाइलर आपको बताएगा कि चेक बेकार है, क्योंकि helloWorld() समारोह वापस नहीं आएगा null, कभी।

पैरामीटर का उपयोग करना

void someMethod(@NotNull someParameter) { }

यदि आप कुछ लिखते हैं:

someMethod(null);

यह संकलित नहीं होगा।

अंतिम उदाहरण का उपयोग कर @Nullable

@Nullable iWantToDestroyEverything() { return null; }

यह कर रहा हूं

iWantToDestroyEverything().something();

और आप सुनिश्चित हो सकते हैं कि ऐसा नहीं होगा। :)

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

IntelliJ IDEA 10.5 और बाद में, उन्होंने किसी अन्य के लिए समर्थन जोड़ा @Nullable  @NotNull कार्यान्वयन।

ब्लॉग पोस्ट देखें अधिक लचीला और विन्यास योग्य @ Nullable / @ NotNull एनोटेशन


518



@NotNull, @Nullable और अन्य शून्यता एनोटेशन का हिस्सा हैं जेएसआर 305। आप उन्हें उपकरण जैसे संभावित समस्याओं का पता लगाने के लिए भी उपयोग कर सकते हैं FindBugs। - Jacek S
मुझे यह आश्चर्यजनक रूप से परेशान लगता है कि @NotNull और @Nullable इंटरफेस पैकेज में रहते हैं com.sun.istack.internal। (मुझे लगता है कि मैं com.sun को मालिकाना एपीआई का उपयोग करने के बारे में चेतावनियों के साथ जोड़ता हूं।) - Jonik
कोड पोर्टेबिलिटी जेटब्रेन के साथ शून्य हो जाती है। मैं विचार स्तर पर उतरने से पहले दो बार (वर्ग) सोचूंगा। जैसे जैस्के एस ने कहा कि वे जेएसआर का हिस्सा हैं, जिस तरह से मैंने सोचा था कि जेएसआर 303 था। - Java Ka Baby
मुझे सच में नहीं लगता कि एक कस्टम कंपाइलर का उपयोग इस समस्या का एक व्यवहार्य समाधान है। - Shivan Dragon
एनोटेशन के बारे में अच्छी बात, जो @NotNull तथा @Nullable यह है कि जब वे स्रोत कोड को उस सिस्टम द्वारा बनाया गया है जो उन्हें समझ में नहीं आता है तो वे अच्छी तरह से अपमानित होते हैं। तो, असल में, तर्क यह है कि कोड पोर्टेबल नहीं है अमान्य हो सकता है - यदि आप इन एनोटेशन का समर्थन करने और समझने वाली प्रणाली का उपयोग करते हैं, तो आपको कठोर त्रुटि जांच का अतिरिक्त लाभ मिलता है, अन्यथा आपको इससे कम मिलता है लेकिन आपका कोड अभी भी होना चाहिए ठीक निर्माण करें, और आपके चल रहे कार्यक्रम की गुणवत्ता समान है, क्योंकि इन टिप्पणियों को रनटाइम पर लागू नहीं किया गया था। इसके अलावा, सभी कंपाइलर कस्टम हैं ;-) - amn


अगर शून्य मूल्यों की अनुमति नहीं है

यदि आपकी विधि को बाहरी रूप से कहा जाता है, तो इस तरह से कुछ शुरू करें:

public void method(Object object) {
  if (object == null) {
    throw new IllegalArgumentException("...");
  }

फिर, उस विधि के बाकी हिस्सों में, आपको वह पता चलेगा object निरर्थक नहीं है।

यदि यह एक आंतरिक विधि है (एपीआई का हिस्सा नहीं है), बस दस्तावेज है कि यह शून्य नहीं हो सकता है, और यही वह है।

उदाहरण:

public String getFirst3Chars(String text) {
  return text.subString(0, 3);
}

हालांकि, अगर आपकी विधि सिर्फ मूल्य को पास करती है, और अगली विधि इसे आदि पर पास करती है तो यह समस्याग्रस्त हो सकती है। उस स्थिति में आप ऊपर के रूप में तर्क की जांच कर सकते हैं।

अगर शून्य की अनुमति है

यह वास्तव में निर्भर करता है। अगर मुझे लगता है कि मैं अक्सर ऐसा कुछ करता हूं:

if (object == null) {
  // something
} else {
  // something else
}

तो मैं शाखा, और दो पूरी तरह से अलग चीजें करते हैं। कोई बदसूरत कोड स्निपेट नहीं है, क्योंकि मुझे डेटा के आधार पर दो अलग-अलग चीजों को करने की ज़रूरत है। उदाहरण के लिए, क्या मुझे इनपुट पर काम करना चाहिए, या क्या मुझे एक अच्छा डिफ़ॉल्ट मान की गणना करनी चाहिए?


मेरे लिए मुहावरे का उपयोग करना वास्तव में दुर्लभ है "if (object != null && ..."।

यदि आप उदाहरणों को दिखाते हैं कि आप आम तौर पर मुहावरे का उपयोग करते हैं तो उदाहरण आपको उदाहरण देना आसान हो सकता है।


282



IllegalArgumentException फेंकने में क्या बात है? मुझे लगता है कि NullPointerException स्पष्ट होगा, और यदि आप खुद को नल-जांच नहीं करते हैं तो उसे भी फेंक दिया जाएगा। मैं या तो जोर से या कुछ भी नहीं उपयोग करेंगे। - Axel
यह असंभव है कि शून्य से हर दूसरे मूल्य स्वीकार्य है। आप IllegalArgumentException, OutOfRageException आदि इत्यादि हो सकता है कभी-कभी यह समझ में आता है। अन्य बार आप कई अपवाद वर्गों को समाप्त करते हैं जो कोई मूल्य नहीं जोड़ते हैं, तो आप केवल IllegalArgumentException का उपयोग करते हैं। यह शून्य-इनपुट के लिए एक अपवाद नहीं है, और बाकी सब कुछ के लिए एक और समझ में आता है। - myplacedk
हां, मैं असफल-सिद्धांत के लिए सहमत हूं, लेकिन ऊपर दिए गए उदाहरण में, मूल्य पारित नहीं किया गया है, लेकिन वह वस्तु है जिस पर एक विधि कहा जाएगा। तो यह समान रूप से तेजी से विफल रहता है, और एक अपवाद फेंकने के लिए सिर्फ एक शून्य जांच जोड़ता है जिसे किसी भी समय और स्थान पर फेंक दिया जाएगा, यह किसी भी आसान डिबगिंग को प्रतीत नहीं होता है। - Axel
एक सुरक्षा छेद? जेडीके इस तरह के कोड से भरा है। यदि आप नहीं चाहते हैं कि उपयोगकर्ता स्टैकट्रैक देखें, तो बस उन्हें अक्षम करें। कोई भी इस बात का निहित नहीं है कि व्यवहार दस्तावेज नहीं है। MySQL सी में लिखा गया है जहां निरर्थक नल पॉइंटर्स अपरिभाषित व्यवहार है, अपवाद फेंकने की तरह कुछ नहीं। - fgb
throw new IllegalArgumentException("object==null") - Thorbjørn Ravn Andersen


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

एलेक्स मिलर द्वारा दिया गया उदाहरण इस तरह दिखता है:

public String getPostcode(Person person) {  
  return person?.getAddress()?.getPostcode();  
}  

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


अद्यतन करें: एक आधिकारिक प्रस्ताव जावा 7 में एक नल-सुरक्षित ऑपरेटर के लिए सबमिट किया गया है परियोजना सिक्का वाक्यविन्यास ऊपर दिए गए उदाहरण से थोड़ा अलग है, लेकिन यह वही धारणा है।


अद्यतन करें: नल-सुरक्षित ऑपरेटर प्रस्ताव ने इसे परियोजना सिक्का में नहीं बनाया। तो, आप जावा 7 में यह वाक्यविन्यास नहीं देख पाएंगे।


215



मुझे लगता है कि यह गलत है। यह निर्दिष्ट करने का एक तरीका होना चाहिए कि एक दिया गया चर हमेशा गैर-शून्य है। - Thorbjørn Ravn Andersen
अद्यतन: प्रस्ताव जावा 7 नहीं बनाएगा। देख blogs.sun.com/darcy/entry/project_coin_final_five । - Boris Terzic
दिलचस्प विचार लेकिन वाक्यविन्यास की पसंद बेतुका है; मैं नहीं चाहता कि प्रत्येक संयुक्त में पिन कोड से भरा कोडबेस भरा हुआ हो। - Rob
यह ऑपरेटर मौजूद है ग्रूवी, इसलिए जो लोग इसका उपयोग करना चाहते हैं, वे अभी भी एक विकल्प के रूप में हैं। - Muhd
यह मैंने देखा है सबसे सरल विचार है। इसे सी वाक्यविन्यास की हर समझदार भाषा में जोड़ा जाना चाहिए। मैं लाइनों के स्क्रीनफुल या चकमा "गार्ड क्लॉज" के माध्यम से स्क्रॉल करने के बजाय हर जगह "प्रश्न चिह्न चिह्न" चाहता हूं। - Victor


यदि अपरिभाषित मानों की अनुमति नहीं है:

संभावित नल dereferencing के बारे में आपको चेतावनी देने के लिए आप अपने आईडीई को कॉन्फ़िगर कर सकते हैं। जैसे ग्रहण में, देखें प्राथमिकताएं> जावा> कंपाइलर> त्रुटियां / चेतावनी / शून्य विश्लेषण

यदि अपरिभाषित मानों की अनुमति है:

यदि आप एक नया एपीआई परिभाषित करना चाहते हैं जहां अपरिभाषित मान समझ में आते हैं, उपयोग विकल्प पैटर्न (कार्यात्मक भाषाओं से परिचित हो सकता है)। इसके निम्नलिखित फायदे हैं:

  • यह स्पष्ट रूप से एपीआई में कहा गया है कि कोई इनपुट या आउटपुट मौजूद है या नहीं।
  • कंपाइलर आपको "अपरिभाषित" केस को संभालने के लिए मजबूर करता है।
  • विकल्प एक मोनड है, इसलिए वर्बोज़ नल जांच की कोई ज़रूरत नहीं है, केवल मूल्य का उपयोग करने के लिए मानचित्र / foreach / getOrElse या एक समान संयोजक का उपयोग करें (उदाहरण)

जावा 8 में अंतर्निहित है Optional कक्षा (अनुशंसित); पिछले संस्करणों के लिए, लाइब्रेरी विकल्प हैं, उदाहरण के लिए अमरूदकी Optional या FunctionalJavaकी Option। लेकिन जावा में विकल्प (यहां तक ​​कि 8) का उपयोग करके कई कार्यात्मक-शैली पैटर्न की तरह, कुछ बॉयलरप्लेट में परिणाम होते हैं, जिन्हें आप कम वर्बोज़ जेवीएम भाषा का उपयोग करके कम कर सकते हैं, उदा। स्कैला या एक्सटेन्ड।

यदि आपको एक एपीआई से निपटना है जो नल वापस कर सकता है, आप जावा में ज्यादा कुछ नहीं कर सकते हैं। Xtend और Groovy है एल्विस ऑपरेटर  ?: और यह शून्य-सुरक्षित dereference ऑपरेटर  ?., लेकिन ध्यान दें कि यह शून्य संदर्भ के मामले में शून्य हो जाता है, इसलिए यह शून्य के उचित संचालन को "स्थगित" करता है।


177



वास्तव में, विकल्प पैटर्न भयानक है। कुछ जावा समकक्ष मौजूद हैं। अमरूद में इसका एक सीमित संस्करण होता है जिसे वैकल्पिक कहा जाता है जो अधिकांश कार्यात्मक सामग्री को छोड़ देता है। हास्केल में, इस पैटर्न को शायद कहा जाता है। - Ben Hardy
जावा 8 में एक वैकल्पिक कक्षा उपलब्ध होगी - Pierre Henry
... और यह (अभी तक) मानचित्र नहीं है और न ही फ्लैटमैप: download.java.net/jdk8/docs/api/java/util/Optional.html - thSoft
वैकल्पिक पैटर्न कुछ भी हल नहीं करता है; एक संभावित नल वस्तु के बजाय, अब आपके पास दो हैं। - Boann
@ बोएन, अगर देखभाल के साथ प्रयोग किया जाता है, तो आप अपनी सभी एनपीई समस्याओं को हल करते हैं। यदि नहीं, तो मुझे लगता है कि एक "उपयोग" समस्या है। - Louis F.


केवल इस स्थिति के लिए -

एक बराबर विधि का आह्वान करने से पहले एक चर शून्य है या नहीं, यह जांच नहीं कर रहा है (एक स्ट्रिंग नीचे उदाहरण की तुलना करें):

if ( foo.equals("bar") ) {
 // ...
}

परिणामस्वरूप एक होगा NullPointerException अगर foo अस्तित्व में नहीं है

यदि आप अपनी तुलना करते हैं तो आप इससे बच सकते हैं Stringइस तरह है:

if ( "bar".equals(foo) ) {
 // ...
}

160



मैं सहमत हूं - केवल उस स्थिति में। मैं प्रोग्रामर खड़े नहीं हो सकता जो इसे अगले अनावश्यक स्तर पर ले गए हैं और लिखते हैं कि अगर (शून्य! = MyVar) ... बस मुझे बदसूरत लग रहा है और कोई उद्देश्य नहीं देता है! - Alex Worden
यह एक विशेष उदाहरण है, संभवतः सबसे सामान्य प्रथा का सबसे अधिक उपयोग किया जाता है: यदि आप इसे जानते हैं, तो हमेशा करें <object that you know that is not null>.equals(<object that might be null>);। यह अन्य तरीकों के लिए काम करता है equals अगर आप अनुबंध जानते हैं और वे विधियां संभाल सकती हैं null मापदंडों। - Stef
यह पहला उदाहरण है जिसे मैंने देखा है योड स्थितियां वास्तव में समझ में आता है - Erin Drummond
NullPointerExceptions एक कारण के लिए फेंक दिया जाता है। उन्हें फेंक दिया जाता है क्योंकि एक वस्तु शून्य है जहां यह नहीं होना चाहिए। यह प्रोग्रामर नौकरी को ठीक करने के लिए नौकरी है, समस्या को छिपाएं नहीं। - Oliver Watkins
कोशिश करें-पकड़ो कुछ भी समस्या को छुपाता नहीं है, यह भाषा में गायब चीनी के आसपास काम करने के लिए एक वैध अभ्यास है। - echox


जावा 8 के साथ नया आता है java.util.Optional वर्ग जो तर्कसंगत रूप से कुछ समस्या हल करता है। कोई कम से कम कह सकता है कि यह कोड की पठनीयता में सुधार करता है, और सार्वजनिक एपीआई के मामले में एपीआई का अनुबंध ग्राहक डेवलपर को स्पष्ट करता है।

वे इस तरह काम करते हैं:

किसी दिए गए प्रकार के लिए एक वैकल्पिक वस्तु (Fruit) एक विधि के रिटर्न प्रकार के रूप में बनाया गया है। यह खाली हो सकता है या एक हो सकता है Fruit वस्तु:

public static Optional<Fruit> find(String name, List<Fruit> fruits) {
   for (Fruit fruit : fruits) {
      if (fruit.getName().equals(name)) {
         return Optional.of(fruit);
      }
   }
   return Optional.empty();
}

अब इस कोड को देखें जहां हम एक सूची खोजते हैं Fruit (fruits) एक दिए गए फल उदाहरण के लिए:

Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
   Fruit fruit = found.get();
   String name = fruit.getName();
}

आप इसका उपयोग कर सकते हैं map() ऑपरेटर पर एक गणना करने के लिए - या एक वैकल्पिक वस्तु से एक मूल्य निकालने के लिए ऑपरेटर। orElse() आपको अनुपलब्ध मानों के लिए फ़ॉलबैक प्रदान करने देता है।

String nameOrNull = find("lemon", fruits)
    .map(f -> f.getName())
    .orElse("empty-name");

बेशक, शून्य / खाली मूल्य की जांच अभी भी जरूरी है, लेकिन कम से कम डेवलपर को पता है कि मूल्य खाली हो सकता है और जांच को भूलने का जोखिम सीमित है।

एक एपीआई में उपयोग करके खरोंच से बनाया गया Optional जब भी वापसी मूल्य खाली हो सकता है, और केवल एक सादा वस्तु वापस कर सकता है जब यह नहीं हो सकता है null (सम्मेलन), क्लाइंट कोड सरल वस्तु वापसी मूल्यों पर शून्य जांच छोड़ सकता है ...

बेशक Optional एक विधि तर्क के रूप में भी इस्तेमाल किया जा सकता है, शायद कुछ मामलों में 5 या 10 ओवरलोडिंग विधियों की तुलना में वैकल्पिक तर्कों को इंगित करने का एक बेहतर तरीका।

Optional अन्य सुविधाजनक तरीकों की पेशकश करता है, जैसे कि orElse जो डिफ़ॉल्ट मान के उपयोग की अनुमति देता है, और ifPresent जो काम करता है लैम्ब्डा अभिव्यक्तियां

मैं आपको इस लेख को पढ़ने के लिए आमंत्रित करता हूं (इस उत्तर को लिखने के लिए मेरा मुख्य स्रोत) जिसमें NullPointerException (और सामान्य शून्य सूचक में) समस्याग्रस्त और साथ ही (आंशिक) समाधान लाया गया Optional अच्छी तरह से समझाया गया है: जावा वैकल्पिक ऑब्जेक्ट्स


135



Google के अमरूद में जावा 6+ के लिए एक वैकल्पिक प्रत्यारोपण है। - Bradley Gottfried
आईटी इस बहुत जोर देने के लिए महत्वपूर्ण है कि केवल वैकल्पिक के साथ ifPresent () करता है नहीं सामान्य शून्य जांच से अधिक मूल्य जोड़ें। यह मूल मूल्य यह है कि यह एक मोनैड है जिसका उपयोग मानचित्र / फ्लैपमैप की फ़ंक्शन चेन में किया जा सकता है, जो ग्रोवी में एल्विस ऑपरेटर के समान परिणाम प्राप्त करता है। यहां तक ​​कि इस उपयोग के बिना भी, मुझे लगता है कि OrElse / orElseThrow वाक्यविन्यास भी बहुत उपयोगी है। - Cornel Masson
इस ब्लॉग में वैकल्पिक पर एक अच्छी प्रविष्टि है winterbe.com/posts/2015/03/15/avoid-null-checks-in-java - JohnC
मैं वास्तव में कभी नहीं समझता कि लोग इस बॉयलरप्लेट कोड से इतने खुश क्यों हैं dzone.com/articles/java-8-elvis-operator - Mykhaylo Adamovych
लोगों को ऐसा करने की प्रवृत्ति क्यों है if(optional.isPresent()){ optional.get(); } के बजाय optional.ifPresent(o -> { ...}) - Satyendra Kumar