जावा स्विच के भीतर चरों को घोषित करना और आरंभ करना


99

मेरे पास जावा स्विच के बारे में एक पागल सवाल है।

int key = 2;

switch (key) {
    case 1:
        int value = 1;
        break;
    case 2:
        value = 2;
        System.out.println(value);
        break;
    default:
        break;
}

परिदृश्य 1 - जब keyदो है इसे सफलतापूर्वक के रूप में 2. मूल्य प्रिंट
जब मैं टिप्पणी करने जा रहा हूँ - परिदृश्य 2 value = 2में case 2:यह कह squawks स्थानीय चर मूल्य प्रारंभ नहीं किया गया है

प्रश्न:

परिदृश्य 1: यदि निष्पादन प्रवाह case 1:(( key = 2)) तक नहीं जाता है, तो यह मान चर के प्रकार को कैसे जानता है int?

परिदृश्य 2: यदि कंपाइलर मान चर के प्रकार को जानता है int, तो उसे int value = 1;अभिव्यक्ति में जाना चाहिए case 1:। (घोषणा और प्रारंभिक)। तो फिर क्यों यह sqawrk जब मैं टिप्पणी करने के लिए जा रहा हूँ करता है value = 2में case 2:कहा, स्थानीय चर मूल्य प्रारंभ नहीं किया गया है


13
यह एक पागल सवाल नहीं है, यह एक बहुत अच्छा सवाल है।
biziclop


@PhilippeCarriere वास्तव में, मुझे लगता है कि यह रिवर्स में होना चाहिए - यहाँ उत्तर बेहतर है (भले ही पोस्ट नया हो) क्योंकि जेएलएस का सीधा संदर्भ है, और उस पोस्ट में विभिन्न उत्तरों में शामिल मुद्दे को अच्छी तरह से सारांशित करता है। यह भी देखें
तुनकी

@Tunaki एक डुप्लिकेट के लिए विवरण "यह प्रश्न पहले पूछा गया है" से शुरू होता है। मैं पढ़ रहा हूं कि बाद में पहले वाले के डुप्लिकेट के रूप में चिह्नित किया जाना चाहिए। लेकिन मैं सहमत हूँ कि यह एक अच्छा तत्व है। हो सकता है कि उन्हें किसी तरह विलय कर दिया जाए?
फिलिप कारिएरे

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

जवाबों:


114

मूल रूप से स्कूपिंग के संदर्भ में स्विच स्टेटमेंट विषम हैं। से JLS की धारा 6.3 :

किसी ब्लॉक में स्थानीय चर घोषणा का दायरा ()14.4) शेष खंड है जिसमें घोषणा प्रकट होती है, अपने स्वयं के प्रारंभकर्ता के साथ शुरू होती है और स्थानीय चर घोषणा बयान में दाईं ओर किसी भी अन्य घोषणाओं को शामिल करती है।

आपके मामले case 2में, उसी ब्लॉक में है case 1और उसके बाद दिखाई देता है, भले ही case 1वह कभी भी निष्पादित नहीं होगा ... इसलिए स्थानीय चर दायरे में है और लिखने के लिए उपलब्ध है बावजूद इसके कि आप कभी भी घोषणा को "निष्पादित" नहीं करते हैं। (ऐलान वास्तव में "निष्पादन योग्य" नहीं है, हालांकि आरंभीकरण है।)

यदि आप value = 2;असाइनमेंट पर टिप्पणी करते हैं , तो कंपाइलर को अभी भी पता है कि आप किस चर का उल्लेख कर रहे हैं, लेकिन आप किसी भी निष्पादन पथ से नहीं गुजरे हैं, जो इसे एक मान प्रदान करता है, यही कारण है कि जब आप प्रयास करते हैं तो आपको एक त्रुटि मिलती है कोई अन्य निश्चित रूप से निर्दिष्ट स्थानीय चर नहीं पढ़ें।

मैं आपको दृढ़ता से सलाह दूंगा कि आप अन्य मामलों में घोषित स्थानीय चर का उपयोग करें - यह अत्यधिक भ्रमित कोड की ओर जाता है, जैसा आपने देखा है। जब मैं स्विच स्टेटमेंट में स्थानीय चर पेश करता हूं (जो मैं शायद ही कभी करने की कोशिश करता हूं - मामलों को बहुत कम होना चाहिए, आदर्श रूप से) मैं आमतौर पर एक नया दायरा पेश करना पसंद करता हूं:

case 1: {
    int value = 1;
    ...
    break;
}
case 2: {
    int value = 2;
    ...
    break;
}

मेरा मानना ​​है कि यह स्पष्ट है।


11
+1 के लिए "एक घोषणा वास्तव में" निष्पादन योग्य "नहीं है, हालांकि आरंभीकरण है।" और सलाह के लिए धन्यवाद भी स्कीट।
नामलफर्नकंड

1
JEP-325 एकीकृत के साथ, स्थानीय चर के दायरे की तस्वीर बदल गई है और कोई स्विच ब्लॉकों के बजाय मामलों में समान नाम का उपयोग कर सकता है। हालांकि यह समान ब्लॉक कोडिंग पर भी निर्भर करता है। इसके अलावा, प्रति स्विच मामले में एक चर को सौंपा गया मूल्य स्विच अभिव्यक्तियों के साथ बहुत सुविधाजनक होगा।
नमन

ब्रेसिज़ के साथ एक नया दायरा जोड़ने के लिए अंक। पता भी नहीं था कि तुम ऐसा कर सकते हो।
फ्लोटिंग सनफिश

21

चर घोषित किया गया है (एक इंट के रूप में), लेकिन आरंभीकृत नहीं (एक प्रारंभिक मूल्य निर्दिष्ट)। लाइन के बारे में सोचो:

int value = 1;

जैसा:

int value;
value = 1;

int valueभाग संकलन समय पर संकलक बताता है कि आप एक चर मूल्य है जो एक पूर्णांक है कहा जाता है। value = 1हिस्सा यह initializes, लेकिन वह रन-टाइम में होता है, और सब पर ऐसा नहीं होता है, तो स्विच की कि शाखा में प्रवेश नहीं है।


संकलन समय और क्रम में घोषणा और आरंभीकरण की अच्छी व्याख्या के लिए +1।
namalfernandolk

18

से http://www.coderanch.com/t/447381/java-programmer-SCJP/certification/variable-initialization-within-case-block

घोषणाओं का संकलन समय पर किया जाता है और यह आपके कोड के निष्पादन प्रवाह पर निर्भर नहीं करता है। चूंकि valueस्विच ब्लॉक के स्थानीय दायरे के भीतर घोषित किया गया है, यह उस ब्लॉक में कहीं भी घोषित होने के स्थान से उपयोग करने योग्य है।


1
यह जवाब क्यों दिया जा रहा है? यह सवाल का जवाब नहीं है, पॉल या स्कीट के जवाब के विपरीत ...
ध्रुव गरोला

7
ऐसा होता है। तो, मेरी तरफ से भी +1, एक पैसा।
रविंदर रेड्डी

3

JEP 325 के एकीकरण के साथ : JDK-12 के शुरुआती एक्सेस बिल्ड में एक्सप्रेशंस (पूर्वावलोकन) स्विच करें । कुछ परिवर्तन हैं जो जॉन के उत्तर से देखे जा सकते हैं -

  1. लोकल वैरिएबल स्कोप - स्विच के मामलों में स्थानीय वैरिएबल अब पूरे स्विच ब्लॉक के बजाय केस के लिए स्थानीय हो सकता है। एक उदाहरण (जो जॉन ने समान रूप से अच्छी तरह सेDayव्याख्याकरने का प्रयास किया था)आगे की व्याख्या के लिए एनम वर्ग परविचार करतेहुए:

    public enum Day {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }
    
    // some another method implementation
    Day day = Day.valueOf(scanner.next());
    switch (day) {
        case MONDAY,TUESDAY -> {
            var temp = "mon-tue";
            System.out.println(temp);
        }
        case WEDNESDAY,THURSDAY -> {
            var temp = Date.from(Instant.now()); // same variable name 'temp'
            System.out.println(temp);
        }
        default ->{
            var temp = 0.04; // different types as well (not mandatory ofcourse)
            System.out.println(temp);
        }
    }
  2. स्विच एक्सप्रेशंस - यदि इरादा किसी वैरिएबल को मान असाइन करना है और फिर उसका उपयोग करना है, तो एक बार स्विच एक्सप्रेशन का उपयोग कर सकते हैं। जैसे

    private static void useSwitchExpression() {
        int key = 2;
        int value = switch (key) {
            case 1 ->  1;
            case 2 -> 2;
            default -> {break 0;}
        };
        System.out.println("value = " + value); // prints 'value = 2'
    }

0

यह स्पष्टीकरण मदद कर सकता है।

    int id=1;

    switch(id){
        default: 
            boolean b= false; // all switch scope going down, because there is no scope tag

        case 1:
            b = false;
        case 2:{
            //String b= "test"; you can't declare scope here. because it's in the scope @top
            b=true; // b is still accessible
        }
        case 3:{
            boolean c= true; // case c scope only
            b=true; // case 3 scope is whole switch
        }
        case 4:{
            boolean c= false; // case 4 scope only
        }
    }

0

जावा कल्पना:

https://docs.oracle.com/javase/specs/jls/se12/html/jls-14.html#jls-14.11

लेबल के साथ विराम के कारण अचानक पूरा होने का मामला लेबल के बयान (.714.7) के लिए सामान्य नियम द्वारा नियंत्रित किया जाता है।

https://docs.oracle.com/javase/specs/jls/se12/html/jls-14.html#jls-14.7

लेबल किए गए कथन:

लेबलडस्टेमेंट: पहचानकर्ता: कथन

लेबलडस्टेमेंटनॉशॉर्टआईफ़: आइडेंटिफ़ायर: स्टेटमेंटनॉशॉर्टआईफ़

सी और सी ++ के विपरीत, जावा प्रोग्रामिंग भाषा में कोई गोटो स्टेटमेंट नहीं है; पहचानकर्ता स्टेटमेंट लेबल का उपयोग विराम (statement14.15) के साथ किया जाता है या जारी (appear14.16) स्टेटमेंट को लेबल किए गए स्टेटमेंट में कहीं भी प्रदर्शित किया जाता है।

लेबल किए गए स्टेटमेंट के लेबल का दायरा तुरंत निहित स्टेटमेंट है।

दूसरे शब्दों में, केस 1, केस 2 स्विच स्टेटमेंट के भीतर लेबल हैं। ब्रेक और जारी बयान लेबल पर लागू किए जा सकते हैं।

क्योंकि लेबल स्टेटमेंट का दायरा साझा करते हैं, लेबल के भीतर परिभाषित सभी चर स्विच स्टेटमेंट के दायरे को साझा करते हैं।

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