<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java 中的 Switch 都支持 String 了,為什么不支持 long?

          共 16330字,需瀏覽 33分鐘

           ·

          2021-04-13 09:47

          往期熱門文章:

          1、往期精選優(yōu)秀博文都在這里了!
          2、CTO 說(shuō)了,用錯(cuò) @Autowired 和 @Resource 的人可以領(lǐng)盒飯了
          3、程序員離職事件始末
          4、如何解決MySQL order by limit語(yǔ)句的分頁(yè)數(shù)據(jù)重復(fù)問題?
          5、Java中八個(gè)潛在的內(nèi)存泄露風(fēng)險(xiǎn),你知道幾個(gè)?


          我們知道 Java Switch 支持byte、short、int 類型,在 JDK 1.5 時(shí),支持了枚舉類型,在 JDK 1.7 時(shí),又支持了 String類型。那么它為什么就不能支持 long 類型呢,明明它跟 byte、short、int 一樣都是數(shù)值型,它又是咋支持 String 類型的呢?

          1

          結(jié)論


          不賣關(guān)子,先說(shuō)結(jié)論:

          switch 底層是使用 int 型 來(lái)進(jìn)行判斷的,即使是枚舉、String類型,最終也是轉(zhuǎn)變成 int 型。由于 long 型表示范圍大于 int 型,因此不支持 long 類型。

          下面詳細(xì)介紹下各個(gè)類型是如何被轉(zhuǎn)變成 int 類型的,使用的編譯命令為 javac,反編譯網(wǎng)站為:http://javare.cn

          2

          枚舉類型是咋變成 int 類型的?


          在沒有實(shí)驗(yàn)之前,我想當(dāng)然的認(rèn)為它是不是根據(jù)枚舉的 int 型字段來(lái)計(jì)算的(因?yàn)橐话忝杜e都是一個(gè)int型,一個(gè)string型),但是轉(zhuǎn)念一想,萬(wàn)一枚舉沒有 int 型字段呢,萬(wàn)一有多個(gè) int 型字段呢,所以肯定不是這樣的,下面看實(shí)驗(yàn)吧。

          定義兩個(gè)枚舉類,一個(gè)枚舉類有一個(gè)int型屬性,一個(gè)string型屬性,另外一個(gè)枚舉類只有一個(gè)string屬性:

          public enum SexEnum {  
              MALE(1, "男"),  
              FEMALE(0, "女");  
            
              private int type;  
            
              private String name;  
            
              SexEnum(int type, String name) {  
                  this.type = type;  
                  this.name = name;  
              }  
          }  
          public enum Sex1Enum {  
              MALE("男"),  
              FEMALE("女");  
              private String name;  
            
              Sex1Enum(String name) {  
                  this.name = name;  
              }  
          }  

          然后編寫一個(gè)測(cè)試類,并且讓兩個(gè)枚舉 switch 的 FEMALE 和 MALE 對(duì)應(yīng)的返回值不同:

          public class SwitchTest {  
              public int enumSwitch(SexEnum sex) {  
                  switch (sex) {  
                      case MALE:  
                          return 1;  
                      case FEMALE:  
                          return 2;  
                      default:  
                          return 3;  
                  }  
              }  
            
              public int enum1Switch(Sex1Enum sex) {  
                  switch (sex) {  
                      case FEMALE:  
                          return 1;  
                      case MALE:  
                          return 2;  
                      default:  
                          return 3;  
                  }  
              }  
          }  

          將這幾個(gè)類反編譯下:

          // SexEnum.class  
          public enum SexEnum {  
            
             MALE(1, "鐢?"),  
             FEMALE(0, "濂?");  
             private int type;  
             private String name;  
             // $FF: synthetic field  
             private static final SexEnum[] $VALUES = new SexEnum[]{MALE, FEMALE};  
            
            
             private SexEnum(int var3, String var4) {  
                this.type = var3;  
                this.name = var4;  
             }  
            
          }  
            
          // Sex1Enum.class  
          public enum Sex1Enum {  
            
             MALE("鐢?"),  
             FEMALE("濂?");  
             private String name;  
             // $FF: synthetic field  
             private static final Sex1Enum[] $VALUES = new Sex1Enum[]{MALE, FEMALE};  
            
            
             private Sex1Enum(String var3) {  
                this.name = var3;  
             }  
            
          }  

          反編譯這兩個(gè)枚舉類,發(fā)現(xiàn)其中多了一個(gè) $VALUES 數(shù)組,內(nèi)部包含了所有的枚舉值。繼續(xù)反編譯測(cè)試類:

          // SwitchTest$1.class  
          import com.example.express.test.Sex1Enum;  
          import com.example.express.test.SexEnum;  
            
          // $FF: synthetic class  
          class SwitchTest$1 {  
            
             // $FF: synthetic field  
             static final int[] $SwitchMap$com$example$express$test$SexEnum;  
             // $FF: synthetic field  
             static final int[] $SwitchMap$com$example$express$test$Sex1Enum = new int[Sex1Enum.values().length];  
            
            
             static {  
                try {  
                   $SwitchMap$com$example$express$test$Sex1Enum[Sex1Enum.FEMALE.ordinal()] = 1;  
                } catch (NoSuchFieldError var4) {  
                   ;  
                }  
            
                try {  
                   $SwitchMap$com$example$express$test$Sex1Enum[Sex1Enum.MALE.ordinal()] = 2;  
                } catch (NoSuchFieldError var3) {  
                   ;  
                }  
            
                $SwitchMap$com$example$express$test$SexEnum = new int[SexEnum.values().length];  
            
                try {  
                   $SwitchMap$com$example$express$test$SexEnum[SexEnum.MALE.ordinal()] = 1;  
                } catch (NoSuchFieldError var2) {  
                   ;  
                }  
            
                try {  
                   $SwitchMap$com$example$express$test$SexEnum[SexEnum.FEMALE.ordinal()] = 2;  
                } catch (NoSuchFieldError var1) {  
                   ;  
                }  
            
             }  
          }  

          首先生成了一個(gè)名為 SwitchTest$1.java 的鏈接類,里面定義了兩個(gè)枚舉數(shù)組,這兩個(gè)數(shù)組元素添加的順序完全和測(cè)試類中 switch 類調(diào)用的順序一致。


          枚舉元素在數(shù)組中的下標(biāo)由 ordinal() 函數(shù)決定,該方法就是返回枚舉元素在枚舉類中的序號(hào)。

          這里我們其實(shí)就已經(jīng)知道了,在 switch 語(yǔ)句中,是根據(jù)枚舉元素在枚舉中的序號(hào)來(lái)轉(zhuǎn)變成 int 型的。最后再看下測(cè)試類的反編譯結(jié)果驗(yàn)證下:

          // SwitchTest.class  
          import com.example.express.test.Sex1Enum;  
          import com.example.express.test.SexEnum;  
          import com.example.express.test.SwitchTest.1;  
            
          public class SwitchTest {  
             public int enumSwitch(SexEnum var1) {  
                switch(1.$SwitchMap$com$example$express$test$SexEnum[var1.ordinal()]) {  
                case 1:  
                   return 1;  
                case 2:  
                   return 2;  
                default:  
                   return 3;  
                }  
             }  
            
             public int enum1Switch(Sex1Enum var1) {  
                switch(1.$SwitchMap$com$example$express$test$Sex1Enum[var1.ordinal()]) {  
                case 1:  
                   return 1;  
                case 2:  
                   return 2;  
                default:  
                   return 3;  
                }  
             }  
          }  


          3

          String 類型是咋變成 int 類型的?


          首先我們先知道 char 類型是如何變成 int 類型的,很簡(jiǎn)單,是 ASCII 碼,例如存在 switch 語(yǔ)句:

          public int charSwitch(char c) {  
              switch (c) {  
                  case 'a':  
                      return 1;  
                  case 'b':  
                      return 2;  
                  default:  
                      return Integer.MAX_VALUE;  
              }  
          }  

          反編譯結(jié)果:

          public int charSwitch(char var1) {  
              switch(var1) {  
                  case 97:  
                      return 1;  
                  case 98:  
                      return 2;  
                  default:  
                      return Integer.MAX_VALUE;  
              }  
          }  

          那么對(duì)于 String 來(lái)說(shuō),利用的就是 hashCode() 函數(shù)了,但是 兩個(gè)不同的字符串 hashCode() 是有可能相等的,這時(shí)候就得靠 equals() 函數(shù)了,例如存在 switch 語(yǔ)句:

          public int stringSwitch(String ss) {  
              switch (ss) {  
                  case "ABCDEa123abc":  
                      return 1;  
                  case "ABCDFB123abc":  
                      return 2;  
                  case "helloWorld":  
                      return 3;  
                  default:  
                      return Integer.MAX_VALUE;  
              }  
          }  

          其中字符串 ABCDEa123abc 和 ABCDFB123abc 的 hashCode 是相等的,反編譯結(jié)果為:

          public int stringSwitch(String var1) {  
             byte var3 = -1;  
             switch(var1.hashCode()) {  
                 case -1554135584:  
                    if(var1.equals("helloWorld")) {  
                       var3 = 2;  
                    }  
                    break;  
                 case 165374702:  
                    if(var1.equals("ABCDFB123abc")) {  
                       var3 = 1;  
                    } else if(var1.equals("ABCDEa123abc")) {  
                       var3 = 0;  
                    }  
             }  
            
             switch(var3) {  
                 case 0:  
                    return 1;  
                 case 1:  
                    return 2;  
                 case 2:  
                    return 3;  
                 default:  
                    return Integer.MAX_VALUE;  
             }  
          }  

          可以看到它引入了局部變量 var3,對(duì)于 hashCode 相等情況通過(guò) equals() 方法判斷,最后再判斷 var3 的值。

          4

          它們的包裝類型支持嗎?


          這里以 Integer 類型為例,Character 和 Byte 同理,例如存在 switch 語(yǔ)句:

          public int integerSwitch(Integer c) {  
              switch (c) {  
                  case 1:  
                      return 1;  
                  case 2:  
                      return 2;  
              }  
              return -1;  
          }  

          反編譯結(jié)果為:

          public int integerSwitch(Integer var1) {  
              switch(var1.intValue()) {  
                  case 1:  
                      return 1;  
                  case 2:  
                      return 2;  
                  default:  
                      return -1;  
              }  
          }  

          可以看到,是支持包裝類型的,通過(guò)自動(dòng)拆箱解決。

          那萬(wàn)一包裝類型是 NULL 咋辦,首先我們知道 swtich 的 case 是不給加 null 的,編譯都通不過(guò),那如果傳 null 呢?

          答案是 NPE,畢竟實(shí)際還是包裝類型的拆箱,自然就報(bào)空指針了。

          往期熱門文章:

          1、歷史文章分類導(dǎo)讀列表!精選優(yōu)秀博文都在這里了!》

          2、一個(gè)牛逼的 多級(jí)緩存 實(shí)現(xiàn)方案!
          3、阿里一面:如何保障消息100%投遞成功、消息冪等性?
          4、GitHub 熱榜:被網(wǎng)友瘋狂惡搞的「螞蟻呀嘿」項(xiàng)目終于開源了!
          5、記住!看小電影前一定要檢查一下域名是不是 HTTPS 的,不然....
          6、拿到年終獎(jiǎng)后馬上辭職,厚道嗎?
          7、Redis 內(nèi)存滿了怎么辦?
          8、在 IDE 中玩轉(zhuǎn) GitHub
          9、死磕18個(gè)Java8日期處理,工作必用!
          10、把我坑慘的一個(gè)MySQL雙引號(hào)!

          瀏覽 34
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天躁夜夜躁av天天爽 | 天天射天天日天天操 | 欧美色视频日本免费 | 欧美黄色免费网战 | 北条麻妃亚洲一区在线观看 |