आपका स्विच स्टेटमेंट डेटा प्रकार लंबा, जावा क्यों नहीं हो सकता है?


80

यहाँ सूर्य के जावा ट्यूटोरियल का एक अंश दिया गया है :

एक स्विच के साथ काम करता byte, short, char, और intआदिम डेटा प्रकार। यह भी स्पष्ट किया प्रकार (वर्ग और विरासत में चर्चा) और कुछ विशेष वर्गों के साथ काम करता है कि "रैप" कुछ आदिम प्रकार: Character, Byte, Short, और Integer(सरल डाटा ऑब्जेक्ट्स में चर्चा)।

एक अच्छा कारण होना चाहिए कि क्यों longआदिम डेटा प्रकार की अनुमति नहीं है। क्या कोई जानता है कि यह क्या है?

जवाबों:


52

मुझे लगता है कि कुछ हद तक यह स्विच के विशिष्ट उपयोग पर आधारित एक मनमाना निर्णय था।

एक स्विच अनिवार्य रूप से दो तरीकों से लागू किया जा सकता है (या सिद्धांत रूप में, एक संयोजन): कम संख्या में मामलों के लिए, या जिनके मूल्य व्यापक रूप से फैले हुए हैं, एक स्विच अनिवार्य रूप से अस्थायी चर पर ifs की एक श्रृंखला के बराबर हो जाता है ( मूल्य को केवल एक बार मूल्यांकन किया जाना चाहिए) पर स्विच किया जा रहा है। उन मामलों की एक मध्यम संख्या के लिए जो अधिक या कम लगातार मूल्य में हैं, एक स्विच टेबल का उपयोग किया जाता है (जावा में TABLESWITCH निर्देश), जिसके द्वारा कूदने का स्थान प्रभावी रूप से एक तालिका में देखा जाता है।

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


मुझे "दुर्लभता" वाले तर्क से सहमत होना होगा क्योंकि मैं जावा में थोड़ी देर के लिए विकास कर रहा हूं और मैं कभी भी ऐसी स्थिति में नहीं आया जहां मुझे ज़रूरत हो / अब तक एक लंबे समय तक स्विच करने की कोशिश की।
फोस्टा 12

3
दिमित्रिस, मेरा तर्क थ्रेड-सेफ्टी की एक गलतफहमी पर आधारित नहीं था, बस मुझे नहीं लगता कि आपके द्वारा रखे गए थ्रेड-सेफ़्टी तर्क को आगे रखा जाए।
नील कॉफ़ी

13
सबसे बेवकूफ डिजाइन निर्णय कभी। मेरे पास एक लंबा है जो झंडे का एक गुच्छा है, और मुझे अगर ... और अगर ... और ... पूरी तरह से हास्यास्पद है।
m0skit0

2
मैं w / @ m0skit0 से सहमत हूं। मेरे मामले में, किसी और ने एक एपीआई लिखा है जो लंबे समय से स्थिरांक के रूप में उपयोग कर रहा है, क्योंकि यही वे डीबी में स्टोर करते हैं। अब मैं किसी और के खराब फैसले के कारण स्विच / केस का उपयोग नहीं कर सकता।
कोडशिम्प

1
मैं यह नहीं कह रहा कि यह "दुनिया का अंत" है। और, हां, इसके आस-पास के तरीके हैं, लेकिन वे सभी हैक की तरह लगते हैं। मेरा कहना है कि, डेवलपर्स के रूप में, हमें हमेशा यह सोचने की कोशिश करनी चाहिए कि हम कैसे सोचते हैं कि लोग हमारे द्वारा बनाए गए सामान का उपयोग करेंगे। इस मामले में, किसी ने प्रारंभिक विचार के आधार पर लंबे समय तक स्विच / केस की अनुमति नहीं देने का निर्णय लिया, "जो ईमानदारी से 2 ^ 64% होगा"। हो सकता है कि यह एक निरीक्षण हो। हो सकता है कि कुछ और कारण है कि लोंगों को स्विच नहीं किया जा सकता है कि हम सिर्फ निजी नहीं थे। मेरे लिए, यह समर्थन नहीं करने के लिए बस अजीब लगता है।
कोडशिम्प

21

क्योंकि वे बायोटेक में आवश्यक निर्देशों को लागू नहीं करते थे और आप वास्तव में यह नहीं लिखना चाहते कि कई मामले, कोई फर्क नहीं पड़ता कि "कोड तैयार" कैसे है ...

[संपादित करें: इस उत्तर पर टिप्पणियों से निकाले गए, पृष्ठभूमि पर कुछ अतिरिक्त के साथ]

सटीक होने के लिए, 2 be बहुत सारे मामले हैं और किसी भी कार्यक्रम को एक विधि के साथ लंबे समय से अधिक रखने के लिए जो पूरी तरह से भयावह होने जा रहा है! किसी भी भाषा में। (किसी भी भाषा में किसी भी कोड में मैं जानता हूं कि सबसे लंबा फ़ंक्शन 6k एसएलओसी से थोड़ा अधिक है - हां, यह एक बड़ा है switch- और यह वास्तव में असहनीय है।) यदि आप वास्तव longमें केवल एक intया उससे कम होना चाहिए, जहां आप होने के साथ फंस गए हैं। तब आपको दो वास्तविक विकल्प मिले हैं।

  1. longएक में सेक करने के लिए हैश कार्यों के विषय पर कुछ संस्करण का उपयोग करें int। सबसे सरल एक, केवल उपयोग के लिए जब आपको टाइप गलत हो गया है, तो बस कास्ट करना है! ऐसा करने के लिए अधिक उपयोगी होगा:

    (int) ((x&0xFFFFFFFF) ^ ((x >>> 32) & 0xFFFFFFFF))
    

    परिणाम पर स्विच करने से पहले। आपको उन मामलों को बदलना होगा, जिन्हें आप परीक्षण कर रहे हैं। लेकिन वास्तव में, यह अभी भी भयानक है क्योंकि यह बहुत सारे मामलों की वास्तविक समस्या को संबोधित नहीं करता है।

  2. एक बहुत बेहतर समाधान यदि आप बहुत बड़ी संख्या में मामलों के साथ काम कर रहे हैं, तो अपने डिजाइन को एक Map<Long,Runnable>या कुछ इसी तरह का उपयोग करके बदलना है ताकि आप देख रहे हैं कि किसी विशेष मूल्य को कैसे भेजा जाए। यह आपको मामलों को कई फाइलों में अलग करने की अनुमति देता है, जो केस-काउंट बड़े होने पर प्रबंधित करना बहुत आसान है, हालांकि इसमें शामिल कार्यान्वयन वर्गों के मेजबान के पंजीकरण को व्यवस्थित करने के लिए अधिक जटिल है (एनोटेशन आपको अनुमति देकर मदद कर सकता है स्वचालित रूप से पंजीकरण कोड का निर्माण करें)।

    FWIW, मैंने यह कई साल पहले किया था (हमने परियोजना के माध्यम से नए जारी किए गए J2SE 1.2 भाग के रास्ते पर स्विच किया) जब बड़े पैमाने पर समानांतर हार्डवेयर का अनुकरण करने के लिए एक कस्टम बाइटकोड इंजन का निर्माण किया गया (नहीं, जेवीएम का पुन: उपयोग करना मौलिक रूप से उपयुक्त नहीं होगा। विभिन्न मूल्य और निष्पादन मॉडल शामिल) और इसने कोड switchके सी संस्करण का उपयोग करने वाले बड़े के सापेक्ष कोड को बहुत सरल कर दिया।

टेक-होम संदेश को दोहराने के लिए, switchएक longपर एक संकेत है कि या तो आप अपने कार्यक्रम में गलत तरीके से मिल गया है या आप बहुत भिन्नता के साथ एक प्रणाली का निर्माण कर रहे हैं कि आप कक्षाओं का उपयोग किया जाना चाहिए शामिल है। किसी भी मामले में पुनर्विचार के लिए समय।


1
लेकिन क्या वास्तव में 32 बिट्स से अधिक चौड़ी रेंज को बंद किया जा रहा है? मैंने कभी भी उस कोड के बारे में नहीं सुना है जिसके लिए कई स्विच आर्म्स की जरूरत होती है। इसके बिना, आप कुछ बनाने के लिए सीमा को संकुचित कर सकते हैं (जैसे, हैश फ़ंक्शन के विषय में कुछ भिन्नता का उपयोग करके)। या Map<Long,Runnable>पूरी तरह से समस्या को हल करने के लिए एक का उपयोग करें । :-)
डोनाल्ड फेलो

3
@ लॉर्ड तोर्गामस: संभवतः क्योंकि यह मूर्खतापूर्ण है। एक पल के लिए इसके बारे में सोचें: कोई भी, किसी को भी, एक मेंswitch 2 32 से अधिक हथियारों के साथ कोड क्यों होगा ? कई तत्वों के एक सीमित सेट का चयन करना चाहते हैं, बस कार्यक्रम के मूल डिजाइन में एक गलती की ओर इशारा करते हैं। यह लोग पूछ रहे हैं कि यह केवल इंगित करता है कि ** उन्हें अपना डिज़ाइन गलत मिला है
डोनल फैलो

1
BTW, अगर कोई मेरे साथ इस पर आगे बहस करना चाहता है, तो कृपया लंबे समय तक स्विच करने के लिए उपयोग-केस देकर शुरू करें। अन्यथा हम हमेशा के लिए काल्पनिक के साथ बहस कर रहे होंगे ...
डोनाल्ड फेलो

2
@DonalFellows, ListView के साथ एंड्रॉइड में एक और मामला है। जबकि सूची दृश्य longमें पंक्तियों की संख्या हो सकती है , मुझे विशेष रूप से केवल 4 की आवश्यकता है। यह मेरे लिए एक मामला है जो मुझे longसौंप दिया गया है जो इंगित करता है कि किस पंक्ति पर कार्य किया जा रहा है, और मुझे उस पंक्ति के आधार पर विभिन्न चीजों को करने की आवश्यकता है। मुझे लगता है कि मैं इंट करने के लिए कास्ट कर सकता हूं, लेकिन अगर यह सिर्फ switchचर पर एड कर सकता है तो इससे मेरी जिंदगी आसान हो जाएगी । जैसा कि है, मैं सिर्फ ifऔर else ifइसके बजाय एक स्ट्रिंग का उपयोग कर रहा हूं ।
क्रिश्चियन स्मिथ

7
"टेक-होम संदेश को दोहराना, एक लंबे समय पर स्विच करना चाहते हैं यह एक संकेत है कि या तो आपने अपने प्रोग्राम में गलत तरीके से टाइप किया है" - नहीं यह नहीं है! बीत रहा है एक longमतलब यह नहीं है कि आप सभी संभावनाओं की जांच करने के लिए जा रहे हैं, बस एक होने की तरह intया एक Stringया तो इसका मतलब यह नहीं है। इसका मतलब है कि आपके पास जो मूल्य हैं, जो एक मुट्ठी भर हो सकते हैं, एक बड़ी रेंज है । आप कुछ सरल मामलों की जाँच कर सकते हैं और defaultशेष के लिए गिर सकते हैं । शिफ्ट और कास्ट करने का मतलब है कि आप डेटा खोने का जोखिम लेंगे। निचला रेखा, इसका खराब जावा डिज़ाइन निर्णय उपयोगकर्ता का मुद्दा नहीं है।
jbx

6

क्योंकि लुकअप टेबल इंडेक्स 32 बिट का होना चाहिए।


3
लेकिन तब फिर से एक switchआवश्यक रूप से एक लुकअप टेबल के साथ लागू नहीं किया जाना चाहिए।
जोकिम सॉयर

10
अगर ऐसा होता, तो वे स्ट्रिंग्स के लिए स्विच लागू नहीं कर सकते थे (जैसा कि वे वर्तमान में योजना बनाते हैं)।
दिमित्री आंद्रेउ

1
@DimitrisAndreou हाँ हम अब स्ट्रिंग्स में स्विच कर सकते हैं: D (अब वर्षों के लिए: P)
J. Doe

-11

32 बिट आर्किटेक्चर में एक लंबा, दो शब्दों द्वारा दर्शाया गया है । अब, कल्पना करें कि अपर्याप्त सिंक्रनाइज़ेशन के कारण क्या हो सकता है, स्विच स्टेटमेंट का निष्पादन अपने उच्च 32 बिट्स को एक लिखने से और दूसरे से 32 कम लोगों के साथ एक लंबा अवलोकन करता है! यह जाने की कोशिश कर सकता है .... कौन जानता है कि कहां! मूल रूप से कहीं पर यादृच्छिक। यहां तक ​​कि अगर दोनों स्विच स्टेटमेंट के लिए वैध मामलों का प्रतिनिधित्व करते हैं, तो उनका मजाकिया संयोजन शायद न तो पहले और न ही दूसरे तक ले जाएगा - या इससे भी बदतर, यह एक और वैध, लेकिन असंबंधित मामला हो सकता है!

कम से कम एक इंट (या कम प्रकार) के साथ, कोई फर्क नहीं पड़ता कि आप कितनी बुरी तरह से गड़बड़ करते हैं, स्विच स्टेटमेंट कम से कम एक मूल्य पढ़ेगा जो किसी ने वास्तव में लिखा था , इसके बजाय एक मूल्य "पतली हवा से बाहर"।

बेशक, मैं वास्तविक कारण नहीं जानता (यह 15 साल से अधिक हो गया है, मैं उस पर लंबे समय से ध्यान नहीं दे रहा हूं!), लेकिन अगर आपको पता है कि इस तरह के निर्माण कैसे असुरक्षित और अप्रत्याशित हो सकते हैं, तो आप सहमत होंगे कि यह निश्चित रूप से एक बहुत अच्छा कारण है कि कभी भी लॉन्ग पर स्विच नहीं होता (और जैसा कि लॉन्ग -पून का इरादा है - 32 बिट मशीनें होंगी, यह कारण वैध रहेगा)।


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

नील, आपका तर्क काफी उलझन में है: "लेकिन फिर, एक बार यह परिणाम एक रजिस्टर में या स्टैक पर होता है, यह केवल स्विचिंग थ्रेड द्वारा पहुँचा जाता है और सुरक्षित है"। यकीन है, उस मूल्य का उपयोग कर धागा सुरक्षित है! लेकिन मेरी बात यह है कि उपयोगकर्ता कोड में सिंक्रनाइज़ेशन बग के कारण वह मूल्य _already_ गलत हो सकता है । धागे-सुरक्षित रूप से एक गलत मूल्य का उपयोग करना उपयोगी से कम है :) इस मुद्दे को कभी भी समाप्त नहीं किया जा सकता है: छोटी गाड़ी समवर्ती कोड पहले से ही "पतली हवा से बाहर" / गलत लंबे मूल्य का उत्पादन कर सकती थी, जिसे बाद में स्विच में उपयोग किया जा सकता है, जिससे स्विच किसी ऐसे मामले के पते पर जाएं जो कभी भी निर्दिष्ट नहीं किया गया हो
दिमित्री आंद्रेउ

1
दिमित्रिस, शायद आपके तर्क में कुछ है जो मैं नहीं समझ रहा हूं। उपयोगकर्ता कोड में सिंक्रनाइज़ेशन बग्स के कारण स्विच किया गया मूल्य वास्तव में गलत हो सकता है। लेकिन मुझे विश्वास नहीं है कि स्विच स्टेटमेंट के बारे में कुछ भी निहित है जो अन्य मामलों की तुलना में इसे अधिक संभावना बनाता है। और यह सबसे अच्छा मैं कर सकता हूँ के माध्यम से सोच, मुझे विश्वास नहीं है कि लंबे समय तक पढ़ने / लिखने के लिए स्मृति के गैर-एटमॉसिटी वास्तव में एक मुद्दा है। (चीजों के बारे में सोचने के तरीके से: आप यह तय कर सकते हैं कि अगर एक लंबे समय की तुलना एक ही तर्क के आधार पर करने की अनुमति नहीं थी।)
नील कॉफ़ी

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

7
मुझे पता है कि यह पुराना है और इस पर टिप्पणी करना एक प्रकार की लूट है लेकिन मैं यह रेखांकित करना चाहता हूं कि आपका तर्क भी लागू होता है ifऔर परिणाम सिर्फ उतना ही बुरा होगा: गलत परिणाम ~> गलत शाखा। एक लंबे बनाना if- else- ifएक के बजाय श्रृंखला switchवास्तव में बिल्कुल समान परिणाम प्राप्त करेंगे।
निकोलाई तोलॉग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.