স্ট্রিং সুইচ স্টেটমেন্ট কেন নাল কেস সমর্থন করে না?


125

আমি কেবল ভাবছি যে জাভা 7 switchবিবৃতি কেন কোনও nullমামলা সমর্থন করে না এবং পরিবর্তে ছুড়ে ফেলেছে NullPointerException? নীচে মন্তব্য করা লাইনটি দেখুন (উদাহরণে জাভা টিউটোরিয়াল নিবন্ধswitch থেকে নেওয়া ):

{
    String month = null;
    switch (month) {
        case "january":
            monthNumber = 1;
            break;
        case "february":
            monthNumber = 2;
            break;
        case "march":
            monthNumber = 3;
            break;
        //case null:
        default: 
            monthNumber = 0;
            break;
    }

    return monthNumber;
}

এটি ifপ্রতিটি switchব্যবহারের আগে নাল চেক করার শর্ত এড়াতে পারত ।


12
এর কোনও চূড়ান্ত উত্তর নেই, যেহেতু আমরা ভাষা তৈরির লোক নই। সমস্ত উত্তর খাঁটি অনুমান করা হবে।
asteri

2
চালু করার চেষ্টা nullএকটি ব্যতিক্রম ঘটায়। ifজন্য একটি পরীক্ষা করুন null, তারপরে switchবিবৃতিতে যান।
gparyani

28
থেকে JLS : জাভা প্রোগ্রামিং ভাষার ডিজাইনারদের রায় সালে [একটি নিক্ষেপ NullPointerExceptionখুঁজতে এবং তাতে অভিব্যক্তি মূল্যায়ণ nullরানটাইম এতে রয়েছেন] চুপটি সমগ্র সুইচ বিবৃতি কুঁদন বা (যদি থাকে) পর বিবৃতি চালানো চয়নের চেয়ে ভাল ফল ডিফল্ট লেবেল (যদি থাকে)।
gparyani

3
@gparyani: একটি উত্তর দিন। এটি খুব সরকারী এবং নিশ্চিত মনে হয়।
থিলো

7
@ জেফগোহেলকে: "আপনি সিদ্ধান্ত না নেওয়া ব্যক্তি না হলে কেন কোনও প্রশ্নের উত্তর দেওয়ার কোনও উপায় নেই।" ... ভাল, gparyani মন্তব্য অন্যথায় প্রমাণিত
user541686

উত্তর:


145

Damryfbfnetsi হিসাবে আউট পয়েন্ট মন্তব্য, JLS §14.11 নিম্নলিখিত নোট আছে:

nullস্যুইচ লেবেল হিসাবে ব্যবহারের বিরুদ্ধে নিষেধাজ্ঞাগুলি এমন কোনও কোড লেখা থেকে বাধা দেয় যা কখনই কার্যকর করা যায় না। যদি switchঅভিব্যক্তিটি কোনও রেফারেন্স টাইপের হয়, Stringবা বাক্সড আদিম টাইপ বা এনুম টাইপের হয় তবে এক্সপ্রেশনটি nullরান সময়টিতে মূল্যায়ন করলে রান-টাইম ত্রুটি ঘটবে । জাভা প্রোগ্রামিং ভাষার ডিজাইনারদের বিচারে, পুরো switchবিবৃতিটি নিঃশব্দে এড়িয়ে যাওয়া বা defaultলেবেলের পরে (যদি থাকে) বিবৃতিগুলি (যদি থাকে) কার্যকর করার চেয়ে এটি ভাল ফলাফল ।

(জোর আমার)

যদিও সর্বশেষ বাক্যটি ব্যবহারের সম্ভাবনাগুলি এড়িয়ে যায় case null:, এটি যুক্তিসঙ্গত বলে মনে হয় এবং ভাষা ডিজাইনারদের উদ্দেশ্যগুলিতে একটি দৃষ্টিভঙ্গি দেয়।

যদি আমরা বরং বাস্তবায়নের বিশদটি লক্ষ্য করি তবে ক্রিশ্চিয়ান হুজারের এই ব্লগ পোস্টটিতে স্যুইচগুলিতে কেন nullঅনুমতি দেওয়া হচ্ছে না তা সম্পর্কে কিছুটা অন্তর্নিহিত জল্পনা রয়েছে (যদিও এটি enumস্যুইচের পরিবর্তে স্যুইচকে কেন্দ্র করে String):

ফণা অধীনে, switchবিবৃতিটি সাধারণত একটি টেবিলসুইচ বাইট কোডটি সংকলন করে। এবং "শারীরিক" যুক্তি switchপাশাপাশি এর কেসগুলি হয় int। স্যুইচ করার জন্য অন্তর্নির্ম মানটি পদ্ধতিটি প্রয়োগ করে নির্ধারিত হয় Enum.ordinal()। অধ্যক্ষগুলি শূন্য থেকে শুরু হয়।

তার মানে, ম্যাপিং nullকরা 0ভাল ধারণা হবে না। প্রথম এনাম মানের একটি স্যুইচটি শূন্য থেকে পৃথক হতে পারে। এনামদের 1 টি অর্ডিনাল গণনা শুরু করা ভাল ধারণা হতে পারে তবে তবে এটির মতো সংজ্ঞা দেওয়া হয়নি, এবং এই সংজ্ঞাটি পরিবর্তন করা যায় না।

যদিও Stringসুইচ ভিন্নভাবে প্রয়োগ করা হয় , enumসুইচ প্রথম এসে কিভাবে একটি রেফারেন্স ধরনের উপর সুইচিং আচরণ করা উচিত যখন রেফারেন্স জন্য চিহ্ন রেখে null


1
এটির জন্য বাদ দিয়ে case null:যদি বাস্তবায়ন করা হত তবে এর অংশ হিসাবে নাল হ্যান্ডলিংয়ের অনুমতি দেওয়ার জন্য এটি একটি বৃহত উন্নতি হবে String। বর্তমানে সমস্ত Stringপরীক্ষার জন্য যেভাবেই হোক আমরা এটি সঠিকভাবে করতে চাইলে নাল-চেক করা দরকার, যদিও বেশিরভাগ স্পষ্টভাবেই স্ট্রিংটির ধ্রুবকটিকে প্রথমে প্রথম হিসাবে রেখে "123test".equals(value)। এখন আমরা আমাদের সুইচ স্টেটমেন্টটি যেমনটি লিখতে বাধ্য if (value != null) switch (value) {...
হচ্ছি

1
পুনরায় "0 এ নাল ম্যাপ করা ভাল ধারণা হবে না": এটি "" .হ্যাশকোড () এর মান 0 হওয়ার পরে এটি একটি স্বল্পমূল্য! এর অর্থ হ'ল একটি নাল স্ট্রিং এবং একটি শূন্য দৈর্ঘ্যের স্ট্রিংটি একটি স্যুইচ বিবৃতিতে অভিন্নরূপে চিকিত্সা করতে হবে, যা স্পষ্টভাবে টেকসই নয়।
স্কোমিসা

এনামের ক্ষেত্রে, তাদের নাল -1 এ ম্যাপিং থেকে কী থামছিল?
ক্রিস্পি

31

সাধারণভাবে nullহ্যান্ডেল করা খারাপ; সম্ভবত একটি ভাল ভাষা ছাড়া বাঁচতে পারে null

আপনার সমস্যার সমাধান হতে পারে

    switch(month==null?"":month)
    {
        ...
        //case "":
        default: 
            monthNumber = 0;

    }

monthখালি স্ট্রিং হলে ভাল ধারণা নয় : এটি নাল স্ট্রিংয়ের মতোই এটি ব্যবহার করবে।
gparyani

13
অনেক ক্ষেত্রে শূন্য স্ট্রিং হিসাবে নালকে চিকিত্সা করা পুরোপুরি যুক্তিসঙ্গত হতে পারে
এরিক উডরুফ

23

এটি সুন্দর নয়, তবে String.valueOf()আপনাকে একটি সুইচে একটি নাল স্ট্রিং ব্যবহার করতে দেয়। যদি এটি সন্ধান করে তবে এটি nullএটিকে রূপান্তরিত করে "null", অন্যথায় এটি ঠিক একই স্ট্রিংটি দেয় যা আপনি এটি পাস করেছেন। আপনি যদি "null"স্পষ্টভাবে পরিচালনা করেন না , তবে এটি চলে যাবে default। একমাত্র সতর্কতাই হ'ল স্ট্রিং "null"এবং একটি আসল nullভেরিয়েবলের মধ্যে পার্থক্য করার কোনও উপায় নেই ।

    String month = null;
    switch (String.valueOf(month)) {
        case "january":
            monthNumber = 1;
            break;
        case "february":
            monthNumber = 2;
            break;
        case "march":
            monthNumber = 3;
            break;
        case "null":
            monthNumber = -1;
            break;
        default: 
            monthNumber = 0;
            break;
    }
    return monthNumber;

2
আমি বিশ্বাস করি জাভাতে এরকম কিছু করা একটি অ্যান্টিপ্যাটার্ন।
asukasz Rzeszotarski

2
@ ŁukaszRzeszotarski এটাই আমি "এটি খুব সুন্দর নয়" বলতে
চাইছিলাম

15

এটি কেন ছুড়ে দেয় তার উত্তর দেওয়ার এটি চেষ্টা NullPointerException

নীচে জাভাপ কমান্ডের আউটপুটটি প্রকাশ করে যা আর্গুমেন্ট স্ট্রিংয়ের caseহ্যাশকোডের উপর ভিত্তি করে বেছে নেওয়া হয়েছিল switchএবং .hashCode()নাল স্ট্রিংয়ের সাথে ডাকা হলে এনপিই নিক্ষেপ করে।

6: invokevirtual #18                 // Method java/lang/String.hashCode:()I
9: lookupswitch  { // 3
    -1826660246: 44
     -263893086: 56
      103666243: 68
        default: 95
   }

এর অর্থ, জাভার হ্যাশকোডের উত্তরের উপর ভিত্তি করে কি বিভিন্ন স্ট্রিংয়ের জন্য একই মান তৈরি করতে পারে? যদিও বিরল, তবুও দুটি মামলার মিল হওয়ার সম্ভাবনা রয়েছে (একই হ্যাশ কোডযুক্ত দুটি স্ট্রিং) নীচে এই উদাহরণটি দেখুন

    int monthNumber;
    String month = args[0];

    switch (month) {
    case "Ea":
        monthNumber = 1;
        break;
    case "FB":
        monthNumber = 2;
        break;
    // case null:
    default:
        monthNumber = 0;
        break;
    }
    System.out.println(monthNumber);

জাভাপ যার জন্য

  10: lookupswitch  { // 1
              2236: 28
           default: 59
      }
  28: aload_3       
  29: ldc           #22                 // String Ea
  31: invokevirtual #24                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
  34: ifne          49
  37: aload_3       
  38: ldc           #28                 // String FB
  40: invokevirtual #24                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
  43: ifne          54
  46: goto          59 //Default

যেহেতু আপনি দেখতে পারেন শুধুমাত্র এক ক্ষেত্রে উত্পন্ন পরার জন্য "Ea"এবং "FB"কিন্তু দুই সঙ্গে ifঅবস্থার প্রতিটি ক্ষেত্রে স্ট্রিং সঙ্গে একটি ম্যাচ জন্য চেক করতে। এই কার্যকারিতা বাস্তবায়নের খুব আকর্ষণীয় এবং জটিল উপায়!


5
যদিও এটি অন্য উপায়ে বাস্তবায়ন করা যেত।
থিলো

2
আমি বলতে চাই এটি একটি নকশা বাগ is
হরিণ হান্টার

6
আমি আশ্চর্য হই যে যদি স্ট্রিং হ্যাশ ফাংশনের কিছু সন্দেহজনক দিকগুলি পরিবর্তিত হয়নি কেন তার সাথে এই সম্পর্কগুলি যুক্ত করা হয়: সাধারণ কোডে hashCodeকোনও প্রোগ্রামের বিভিন্ন রানে একই মানগুলি ফেরত দেওয়ার উপর নির্ভর করা উচিত নয় , তবে স্ট্রিং হ্যাশগুলি এক্সিকিউটেবলের মধ্যে বেকড হয়ে যাওয়ার কারণে সংকলক, স্ট্রিং হ্যাশ পদ্ধতিটি ভাষা বর্ণের অংশ হয়ে শেষ হয়।
সুপারক্যাট

5

দীর্ঘ গল্প সংক্ষিপ্ত ... (এবং আশা করি যথেষ্ট আকর্ষণীয় !!!)

এনাম প্রথমে জাভা ১.৫ ( সেপ্টেম্বর ২০০৪ ) এ প্রবর্তিত হয়েছিল এবং স্ট্রিংয়ে স্যুইচ করার অনুমতি দেওয়ার জন্য অনুরোধ করা বাগটি বহু আগেই ( অক্টোবর 95 ) ফাইল করা হয়েছিল । আপনি যদি জুন ২০০৪- এ সেই বাগটিতে পোস্ট করা মন্তব্যটি দেখুন , এটি বলে মনে হচ্ছে যে তারা এই বাগটি পিছনে ফেলেছে ( উপেক্ষা করেছে ) এবং অবশেষে একই বছরে জাভা 1.5 চালু করেছিল যেখানে তারা 0 থেকে শুরু করে অর্ডিনাল দিয়ে 'এনাম' প্রবর্তন করেছিল এবং সিদ্ধান্ত নিয়েছে ( মিস ) এনামের জন্য নাল সমর্থন না করা। পরে জাভা ১..7 ( জুলাই ২০১১ ) এ তারা অনুসরণ করেছে ( বাধ্য হয়েছে )Don't hold your breath. Nothing resembling this is in our plans.) স্ট্রিংয়ের সাথে একই দর্শন (যেমন বাইটকোড তৈরি করার সময় হ্যাশকোড () পদ্ধতি কল করার আগে কোনও নাল চেক করা হয়নি)।

সুতরাং আমি মনে করি এটি প্রথম দিকে এনাম এসেছিল এবং এটি 0 এর সাধারণ সূচনা দিয়ে বাস্তবায়িত হয়েছিল যার কারণে তারা সুইচ ব্লকের নাল মান সমর্থন করতে পারেনি এবং পরে স্ট্রিংয়ের সাথে তারা একই দর্শনের বাধ্যতামূলক করার সিদ্ধান্ত নিয়েছে অর্থাৎ নাল মানকে নয় সুইচ ব্লকে অনুমোদিত

টিএল; ডিআর স্ট্রিং সহ তারা এনপিই (নালার জন্য হ্যাশকোড তৈরির প্রয়াসের কারণে) কে জাভা কোডটি বাইট কোড রূপান্তর করতে প্রয়োগ করার সময় যত্ন নিতে পারত কিন্তু শেষ পর্যন্ত না করার সিদ্ধান্ত নিয়েছিল।

তথ্যসূত্র : TheBUG , জাভা ভার্সন হিস্টোরি , জাভা কোডোডোবাইটকোড , এসও


1

জাভা ডক্স অনুসারে:

একটি স্যুইচ বাইট, শর্ট, চর এবং ইন আদিম ডেটা ধরণের সাথে কাজ করে। এটি গণনা করা প্রকারগুলি (এনাম টাইপগুলিতে আলোচিত), স্ট্রিং ক্লাস এবং কয়েকটি বিশেষ শ্রেণীর সাথে কাজ করে যা কিছু নির্দিষ্ট আদিম প্রকারগুলি আবদ্ধ করে: চরিত্র, বাইট, সংক্ষিপ্ত এবং পূর্ণসংখ্যা (সংখ্যা এবং স্ট্রিংগুলিতে আলোচিত)।

যেহেতু nullকোনও প্রকার নেই, এবং কোনও কিছুর উদাহরণ নয়, এটি একটি স্যুইচ স্টেটমেন্ট দিয়ে কাজ করবে না।


4
আর nullএকটি জন্য একটি বৈধ মান String, Character, Byte, Short, অথবা Integerরেফারেন্স।
asteri

0

উত্তরটি হ'ল আপনি যদি রেফারেন্স টাইপের (যেমন একটি বক্সযুক্ত আদিম ধরণের) সাথে একটি স্যুইচ ব্যবহার করেন, এক্সপ্রেসনটি বাতিল হয়ে গেলে রান-টাইম ত্রুটি ঘটবে কারণ এটি আনবক্সিং করা এনপিই নিক্ষেপ করবে।

সুতরাং কেস নাল (যা অবৈধ) কখনই কার্যকর করা যায় না;)


1
যদিও এটি অন্য উপায়ে বাস্তবায়ন করা যেত।
থিলো

ঠিক আছে @ থিলো, আমার চেয়ে বেশি বুদ্ধিমান লোকেরা এই বাস্তবায়নে জড়িত ছিল। আপনি যদি অন্য কোন উপায়ে এটি প্রয়োগ করতে পারতেন তবে যদি সেগুলি জানতে পারি তবে আমি সেগুলি কী তা জানতে আগ্রহী [এবং আমি নিশ্চিত অন্যরাও রয়েছেন] তাই ভাগ করুন ...
অমিত

3
স্ট্রিংগুলি বাক্সিত আদিম ধরণের নয় এবং এনপিই ঘটে না কারণ কেউ এগুলি "আনবক্স" করার চেষ্টা করছে।
থিলো

@ তিলো, এটি বাস্তবায়নের অন্যান্য উপায়গুলি কী?
অমৃত

3
if (x == null) { // the case: null part }
থিলো

0

আমি @ পল বেলোরার উত্তরে https://stackoverflow.com/a/18263594/1053496 এ অন্তর্দৃষ্টিপূর্ণ মন্তব্যে (হুডের নীচে ....) একমত

আমি আমার অভিজ্ঞতা থেকে আরও একটি কারণ খুঁজে পেয়েছি।

যদি 'কেস' নাল হতে পারে তার অর্থ সুইচ (ভেরিয়েবল) নাল হয় তবে যতক্ষণ ডেভলপাররা 'নাল' কে মিলে যায় তবে আমরা তর্ক করতে পারি এটি ঠিক আছে। তবে বিকাশকারী কোনও মিলে যাওয়া 'নাল' কেস সরবরাহ না করলে কী হবে। তারপরে আমাদের এটি একটি 'ডিফল্ট' কেসের সাথে মেলে ফেলতে হবে যা বিকাশকারী ডিফল্ট ক্ষেত্রে হ্যান্ডেল করার পরিকল্পনা করেছিল তা নাও হতে পারে। সুতরাং 'নাল' কে ডিফল্টর সাথে মিলে ফেললে 'অবাক করা আচরণ' হতে পারে। সুতরাং 'এনপিই' নিক্ষেপ করা বিকাশকারীকে প্রতিটি কেস স্পষ্টভাবে পরিচালনা করতে সক্ষম করবে। আমি এই ক্ষেত্রে এনপিই নিক্ষেপ করতে দেখেছি খুব চিন্তাশীল।


0

অ্যাপাচি স্ট্রিংউটিলস ক্লাসটি ব্যবহার করুন

String month = null;
switch (StringUtils.trimToEmpty(month)) {
    case "xyz":
        monthNumber=1;  
    break;
    default:
       monthNumber=0;
    break;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.