成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java中的Switch是如何支持String的?為什么不支持long?

開(kāi)發(fā) 后端
Java Switch 為什么就不能支持 long 類(lèi)型呢,明明它跟 byte、short、int 一樣都是數(shù)值型,它又是咋支持 String 類(lèi)型的呢?一起來(lái)看一下吧。

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

一、結(jié)論

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

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

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

二、枚舉類(lèi)型是咋變成 int 類(lèi)型的?

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

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

  1. public enum SexEnum {    
  2.     MALE(1, "男"),    
  3.     FEMALE(0, "女");    
  4.     private int type;   
  5.      private String name;   
  6.      SexEnum(int type, String name) {   
  7.         this.type = type;    
  8.         this.name = name;    
  9.     }   
  10.  }    
  1. public enum Sex1Enum {    
  2.     MALE("男"),    
  3.     FEMALE("女");    
  4.     private String name;     
  5.     Sex1Enum(String name) { 
  6.          this.name = name;   
  7.     }    
  8. }   

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

  1. public class SwitchTest {   
  2.     public int enumSwitch(SexEnum sex) {    
  3.         switch (sex) {    
  4.             case MALE:    
  5.                 return 1;    
  6.             case FEMALE:    
  7.                 return 2;    
  8.             default:    
  9.                 return 3;   
  10.         }    
  11.     }   
  12.      public int enum1Switch(Sex1Enum sex) {    
  13.         switch (sex) {    
  14.             case FEMALE:    
  15.                 return 1;    
  16.             case MALE:    
  17.                 return 2;    
  18.             default:    
  19.                 return 3;    
  20.         }    
  21.     }    
  22. }   

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

  1. // SexEnum.class    
  2. public enum SexEnum {   
  3.     MALE(1, "鐢�"),    
  4.    FEMALE(0, "濂�");    
  5.    private int type;    
  6.    private String name;    
  7.    // $FF: synthetic field    
  8.    private static final SexEnum[] $VALUES = new SexEnum[]{MALE, FEMALE};   
  9.     private SexEnum(int var3, String var4) {   
  10.       this.type = var3;    
  11.       this.name = var4;    
  12.    }    
  13. }   
  14.  // Sex1Enum.class    
  15. public enum Sex1Enum {    
  16.     MALE("鐢�"),  
  17.     FEMALE("濂�");   
  18.    private String name;    
  19.    // $FF: synthetic field    
  20.    private static final Sex1Enum[] $VALUES = new Sex1Enum[]{MALE, FEMALE};    
  21.     private Sex1Enum(String var3) {    
  22.       this.name = var3;    
  23.    }   
  24.  }   

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

  1. // SwitchTest$1.class    
  2. import com.example.express.test.Sex1Enum;  
  3. import com.example.express.test.SexEnum;    
  4. // $FF: synthetic class    
  5. class SwitchTest$1 {   
  6.     // $FF: synthetic field    
  7.    static final int[] $SwitchMap$com$example$express$test$SexEnum;    
  8.    // $FF: synthetic field    
  9.    static final int[] $SwitchMap$com$example$express$test$Sex1Enum = new int[Sex1Enum.values().length];   
  10.     static {    
  11.       try {    
  12.          $SwitchMap$com$example$express$test$Sex1Enum[Sex1Enum.FEMALE.ordinal()] = 1 
  13.        } catch (NoSuchFieldError var4) {    
  14.          ;    
  15.       }        
  16.       try {    
  17.          $SwitchMap$com$example$express$test$Sex1Enum[Sex1Enum.MALE.ordinal()] = 2; 
  18.        } catch (NoSuchFieldError var3) {    
  19.          ;   
  20.       }    
  21.       $SwitchMap$com$example$express$test$SexEnum = new int[SexEnum.values().length];    
  22.        try {    
  23.          $SwitchMap$com$example$express$test$SexEnum[SexEnum.MALE.ordinal()] = 1;    
  24.       } catch (NoSuchFieldError var2) {    
  25.          ;    
  26.       }    
  27.        try {    
  28.          $SwitchMap$com$example$express$test$SexEnum[SexEnum.FEMALE.ordinal()] = 2;    
  29.       } catch (NoSuchFieldError var1) {    
  30.          ;    
  31.       }   
  32.     }    
  33. }   

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

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

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

  1. // SwitchTest.class    
  2. import com.example.express.test.Sex1Enum;    
  3. import com.example.express.test.SexEnum;    
  4. import com.example.express.test.SwitchTest.1;   
  5. public class SwitchTest {   
  6.    public int enumSwitch(SexEnum var1) {   
  7.        switch(1.$SwitchMap$com$example$express$test$SexEnum[var1.ordinal()]) {    
  8.       case 1:    
  9.          return 1;    
  10.       case 2:    
  11.          return 2;    
  12.       default:    
  13.          return 3;    
  14.       }    
  15.    }    
  16.    public int enum1Switch(Sex1Enum var1) {    
  17.       switch(1.$SwitchMap$com$example$express$test$Sex1Enum[var1.ordinal()]) {    
  18.       case 1:    
  19.          return 1;  
  20.        case 2:    
  21.          return 2;  
  22.        default:    
  23.          return 3;    
  24.       }    
  25.    }    
  26. }   

三、String 類(lèi)型是咋變成 int 類(lèi)型的?

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

 

  1. public int charSwitch(char c) {    
  2.     switch (c) {    
  3.         case 'a':    
  4.             return 1;   
  5.         case 'b':    
  6.             return 2;    
  7.         default:    
  8.             return Integer.MAX_VALUE;    
  9.     }    
  10. }   

反編譯結(jié)果: 

  1. public int charSwitch(char var1) {    
  2.     switch(var1) { 
  3.          case 97:    
  4.             return 1;    
  5.         case 98:    
  6.             return 2;    
  7.         default:    
  8.             return Integer.MAX_VALUE;    
  9.     }    
  10. }   

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

  1. public int stringSwitch(String ss) {   
  2.     switch (ss) {    
  3.         case "ABCDEa123abc":    
  4.             return 1;    
  5.         case "ABCDFB123abc":    
  6.             return 2;    
  7.         case "helloWorld":   
  8.             return 3;    
  9.         default:    
  10.             return Integer.MAX_VALUE;    
  11.     }    
  12. }   

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

  1. public int stringSwitch(String var1) {    
  2.    byte var3 = -1;    
  3.    switch(var1.hashCode()) {    
  4.        case -1554135584:    
  5.           if(var1.equals("helloWorld")) {  
  6.              var3 = 2;    
  7.           }    
  8.           break;    
  9.        case 165374702:    
  10.           if(var1.equals("ABCDFB123abc")) {    
  11.              var3 = 1;    
  12.           } else if(var1.equals("ABCDEa123abc")) {    
  13.              var3 = 0;    
  14.           }    
  15.    }    
  16.    switch(var3) {   
  17.        case 0:    
  18.           return 1;    
  19.        case 1:    
  20.           return 2;    
  21.        case 2:    
  22.           return 3;    
  23.        default:    
  24.           return Integer.MAX_VALUE;    
  25.    }    
  26. }   

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

四、它們的包裝類(lèi)型支持嗎?

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

  1. public int integerSwitch(Integer c) {    
  2.     switch (c) {    
  3.         case 1:    
  4.             return 1; 
  5.          case 2:    
  6.             return 2;    
  7.     }    
  8.     return -1;    
  9. }   

反編譯結(jié)果為: 

  1. public int integerSwitch(Integer var1) {    
  2.     switch(var1.intValue()) {    
  3.         case 1:    
  4.             return 1;    
  5.         case 2:    
  6.             return 2;    
  7.         default:    
  8.             return -1;    
  9.     }    
  10. }   

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

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

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

 

責(zé)任編輯:龐桂玉 來(lái)源: Java知音
相關(guān)推薦

2021-02-01 13:53:53

StringlongJava

2020-10-09 06:48:19

Pythonswitch語(yǔ)句

2021-10-27 07:15:36

Go 循環(huán)引用

2020-07-22 08:01:41

Python開(kāi)發(fā)運(yùn)算符

2021-04-20 19:23:07

語(yǔ)法switch-casePython

2021-12-09 10:51:47

Go類(lèi)繼承

2021-12-15 07:49:22

Go語(yǔ)言設(shè)計(jì)

2011-12-09 20:28:50

2021-07-13 08:09:34

微博推特評(píng)論

2024-01-01 08:10:40

Go語(yǔ)言map

2024-01-05 08:45:35

Go語(yǔ)言map

2024-05-28 08:55:52

2023-01-28 08:05:32

轉(zhuǎn)換Go泛型

2009-03-12 08:42:38

AndroidWMMTK

2021-11-08 11:02:01

Go函數(shù)重載

2021-06-11 00:03:31

鴻蒙智能手機(jī)

2021-08-02 09:31:20

Python工具代碼

2023-03-07 21:43:29

Java多重繼承

2021-03-02 06:03:30

Java繼承對(duì)象

2016-11-08 09:04:20

ChromeHTTP網(wǎng)站
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产真实乱全部视频 | 久久久久久久久99 | 精品久久久久久亚洲综合网 | 97人澡人人添人人爽欧美 | 日本一区二区高清不卡 | 日韩精品一区二区三区中文在线 | 久久99精品久久久久久国产越南 | 日本亚洲精品成人欧美一区 | 91av视频在线播放 | 久久久一区二区三区 | 日本精品一区二区在线观看 | 久久久久91 | 一道本在线 | 天天干在线播放 | 91视频在线观看 | 免费一级片 | 日韩aⅴ片 | 精品小视频| 午夜精品久久久久久久久久久久久 | 精品乱子伦一区二区三区 | 日韩电影免费在线观看中文字幕 | 成人午夜精品 | 精国产品一区二区三区 | 中文字幕视频三区 | 国产一区二区三区久久久久久久久 | 国产精品久久久久久久久久久免费看 | 久久精品久久综合 | 国产精品免费一区二区 | 四虎最新视频 | 亚洲日本国产 | 大学生a级毛片免费视频 | 91久久精品一区二区二区 | 久久亚洲国产 | 亚洲一区视频在线 | 亚洲精品在线免费观看视频 | 欧美一区免费 | aaa国产大片| 国产精品久久久久久婷婷天堂 | caoporn国产精品免费公开 | 久久精品亚洲一区 | 日本在线免费 |