स्विच में नल का उपयोग कैसे करें


202
Integer i = ...

switch (i){
    case null:
        doSomething0();
        break;    
    }

ऊपर के कोड में मैं स्विच केस स्टेटमेंट में शून्य का उपयोग कर सकता हूं। मैं इसे अलग तरह से कैसे कर सकता हूं? मैं उपयोग नहीं कर सकता defaultक्योंकि तब मैं कुछ और करना चाहता हूं।


9
अशक्त स्थिति के लिए स्विच चेक करने से पहले यदि (i == null) {// dosomething}
नागराजू बडैनी

8
यह वास्तव में स्विच को उपयोगी बनाएगा। अन्य पैटर्न से मेल खाने वाली भाषाएँ इस तरह से काम करती हैं।
पाइरोलॉनिक

जवाबों:


276

switchजावा में एक बयान के साथ यह संभव नहीं है । nullइससे पहले की जाँच करें switch:

if (i == null) {
    doSomething0();
} else {
    switch (i) {
    case 1:
        // ...
        break;
    }
}

आप switchबयानों में मनमानी वस्तुओं का उपयोग नहीं कर सकते हैं * । कारण यह है कि संकलक के बारे में शिकायत नहीं कर रहा है switch (i), जहां iएक है Integerजावा ऑटो unboxes वजह से है Integerएक करने के लिए int। जैसा कि पहले ही कहा assylias, unboxing एक फेंक होगा NullPointerExceptionजब iहै null

* जावा 7 के बाद से आप बयानों Stringमें उपयोग कर सकते हैं switch

Oracle डॉक्स - स्विच के बारे में switch(उदाहरण सहित अशक्त चर)


16
आप स्विच स्टेटमेंट में भी एनम का उपयोग कर सकते हैं।
joriki

27
यह समझ में आता है कि आप अशक्त होने के कारण अशक्त पूर्णांक या अन्य आवरण वर्ग का उपयोग नहीं कर सकते। लेकिन एनम और स्ट्रिंग्स के बारे में क्या? वे अशक्त क्यों नहीं हो सकते?
लुआन निको

9
मुझे समझ में नहीं आ रहा है कि नल के शॉर्ट सर्किट को "डिफ़ॉल्ट" केस में मैप क्यों किया जा रहा है या स्ट्रिंग्स के लिए नल स्विच के लिए एक विशेष मामला लागू नहीं किया गया था। यह कोड को सरल बनाने के लिए स्विच का उपयोग करता है क्योंकि आपको हमेशा एक शून्य जांच करनी होती है। मैं यह नहीं कह रहा कि सरलीकरण केवल स्विच के लिए उपयोग है।
रीइमियस

3
@Reimius आपको हमेशा एक अशक्त चेक नहीं करना है। यदि आप उन कोड अनुबंधों का सम्मान करते हैं, जो आप अपने तरीकों से देते हैं, तो आप लगभग हमेशा अपने कोड को अशक्त चेक के साथ बंद नहीं करने का प्रबंधन कर सकते हैं । हालांकि, हमेशा उपयोग करना अच्छा होता है।
जोफ्री

मैं भी @ LuanNico के प्रश्न का उत्तर जानना चाहूंगा। यह अनुचित लगता है कि nullजब Stringऔर enumप्रकार के साथ काम करने के लिए एक वैध मामला नहीं हो सकता है । शायद enumकार्यान्वयन ordinal()पर्दे के पीछे कॉल करने पर निर्भर करता है (हालांकि यहां तक ​​कि, क्यों - null1-1 के 'ऑर्डिनल' होने के रूप में नहीं माना जाता है), और Stringसंस्करण कुछ का उपयोग करता है intern()और पॉइंटर-तुलना (या अन्यथा किसी चीज पर निर्भर करता है जिसे कड़ाई से डेरेफेरिंग की आवश्यकता होती है) वस्तु)?
एरोथ


40

switch(i)अगर मैं है तो NullPointerException को फेंक देगा null, क्योंकि यह Integerएक में इनबॉक्स को खोलने की कोशिश करेगा int। तो case null, जो अवैध होता है, वैसे भी कभी नहीं पहुंचता।

आपको यह जांचने की आवश्यकता है कि मैं switchबयान से पहले अशक्त नहीं हूं ।


23

जावा डॉक्स ने स्पष्ट रूप से कहा कि:

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

आपको Swithch स्टेटमेंट निष्पादन से पहले अशक्त के लिए सत्यापित करना होगा।

if (i == null)

स्विच स्टेटमेंट देखें

case null: // will never be executed, therefore disallowed.

1
आपके लिंक पर मौजूद javadocs अब यह नहीं कहती है "स्विच लेबल [आदि] के रूप में अशक्त उपयोग करने के खिलाफ निषेध"।
पैट्रिक एम


14

दिया हुआ:

public enum PersonType {
    COOL_GUY(1),
    JERK(2);

    private final int typeId;
    private PersonType(int typeId) {
        this.typeId = typeId;
    }

    public final int getTypeId() {
        return typeId;
    }

    public static PersonType findByTypeId(int typeId) {
        for (PersonType type : values()) {
            if (type.typeId == typeId) {
                return type;
            }
        }
        return null;
    }
}

मेरे लिए, यह आम तौर पर एक डेटाबेस में लुक-अप तालिका के साथ संरेखित होता है (केवल शायद ही-अपडेट की गई तालिकाओं के लिए)।

हालांकि, जब मैं findByTypeIdएक स्विच स्टेटमेंट (सबसे अधिक संभावना, उपयोगकर्ता इनपुट) से उपयोग करने का प्रयास करता हूं ...

int userInput = 3;
PersonType personType = PersonType.findByTypeId(userInput);
switch(personType) {
case COOL_GUY:
    // Do things only a cool guy would do.
    break;
case JERK:
    // Push back. Don't enable him.
    break;
default:
    // I don't know or care what to do with this mess.
}

... जैसा कि दूसरों ने कहा है, इसका परिणाम NPE @ है switch(personType) {। एक काम के आसपास (यानी, "समाधान") मैंने लागू करना शुरू कर दिया एक UNKNOWN(-1)प्रकार जोड़ना था ।

public enum PersonType {
    UNKNOWN(-1),
    COOL_GUY(1),
    JERK(2);
    ...
    public static PersonType findByTypeId(int id) {
        ...
        return UNKNOWN;
    }
}

अब, आपको अशक्त-जाँच करने की आवश्यकता नहीं है कि यह कहाँ गिना जाता है और आप UNKNOWNप्रकारों को संभाल सकते हैं या नहीं, चुन सकते हैं । (नोट: -1व्यावसायिक परिदृश्य में एक असंभावित पहचानकर्ता है, लेकिन स्पष्ट रूप से कुछ ऐसा चुनें जो आपके उपयोग-मामले के लिए समझ में आता है)।


2
UNKNOWNइस पर सबसे अच्छा समाधान मैंने कभी देखा है और nullchecks से आगे निकल गया है।
membersound

5

आपको एक बनाना होगा

if (i == null) {
   doSomething0();
} else {
   switch (i) {
   }
}

4

कुछ लाइब्रेरी बिलिन जावा switchस्टेटमेंट के विकल्पों की पेशकश करने का प्रयास करती हैं । Vavr उनमें से एक है, वे इसे पैटर्न मिलान के लिए सामान्यीकृत करते हैं।

यहाँ उनके प्रलेखन से एक उदाहरण है :

String s = Match(i).of(
    Case($(1), "one"),
    Case($(2), "two"),
    Case($(), "?")
);

आप किसी भी विधेय का उपयोग कर सकते हैं, लेकिन वे उनमें से कई को बॉक्स से बाहर की पेशकश करते हैं, और $(null)पूरी तरह से कानूनी है। मुझे यह विकल्प की तुलना में अधिक सुरुचिपूर्ण समाधान लगता है, लेकिन इसके लिए java8 और vavr लाइब्रेरी पर निर्भरता की आवश्यकता होती है ...




0

आप नहीं कर सकते। आप स्विच में आदिम (इंट, चार, शॉर्ट, बाइट) और स्ट्रिंग (केवल जावा 7 में स्ट्रिंग्स) का उपयोग कर सकते हैं। आदिम अशक्त नहीं हो सकते। स्विच से पहले अलग स्थिति में
जांचें i


4
आप एनम का उपयोग भी कर सकते हैं।
कारू

5
अगर एनम अशक्त है, तो आपको वही समस्या होगी। BTW, यह बहुत अजीब है कि स्विच अशक्त को संभाल नहीं सकता है, क्योंकि इसमें एक डिफ़ॉल्ट क्लॉज है

1
@ लियोनार्डोकेनजी डिफ़ॉल्ट क्लॉज़ का वास्तव में अशक्त करने के लिए कुछ भी नहीं है; जो भी आप इसे स्विच कर रहे हैं, उसे किसी अन्य मामलों की जांच करने के लिए डिरेल किया जाएगा, इसलिए डिफ़ॉल्ट क्लॉज नल केस को हैंडल नहीं करेगा (एक NullPointerException को फेंक दिया जाता है इससे पहले कि यह एक मौका है)।
बेन

2
मुझे लगता है कि उनका मतलब था कि डिफ़ॉल्ट क्लॉज को किसी अन्य संभावित एनम मूल्य के रूप में शून्य को संभालना चाहिए जो पिछले मामले द्वारा नहीं पकड़ा गया था
लियो

0

ज़रा सोचिए कि SWITCH कैसे काम कर सकता है,

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

0

@Tetsuo उत्तर के आधार पर, जावा 8 के साथ:

Integer i = ...

switch (Optional.ofNullable(i).orElse(DEFAULT_VALUE)) {
    case DEFAULT_VALUE:
        doDefault();
        break;    
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.