偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

switch是如何支持String的?為什么不支持long?

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

 我們知道 Java Switch 支持byte、short、int 類型,在 JDK 1.5 時,支持了枚舉類型,在 JDK 1.7 時,又支持了 String類型。

那么它為什么就不能支持 long 類型呢,明明它跟 byte、short、int 一樣都是數(shù)值型,它又是咋支持 String 類型的呢?

一、結論

不賣關子,先說結論:

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

下面詳細介紹下各個類型是如何被轉變成 int 類型的,使用的編譯命令為 javac。

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

在沒有實驗之前,我想當然的認為它是不是根據(jù)枚舉的 int 型字段來計算的(因為一般枚舉都是一個int型,一個string型),但是轉念一想,萬一枚舉沒有 int 型字段呢,萬一有多個 int 型字段呢,所以肯定不是這樣的,下面看實驗吧。

定義兩個枚舉類,一個枚舉類有一個int型屬性,一個string型屬性,另外一個枚舉類只有一個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. }    
  11. public enum Sex1Enum {    
  12.     MALE("男"),    
  13.     FEMALE("女");    
  14.     private String name;   
  15.     Sex1Enum(String name) {    
  16.         this.name = name;    
  17.     }    
  18. }   

然后編寫一個測試類,并且讓兩個枚舉 switch 的 FEMALE 和 MALE 對應的返回值不同: 

  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. }   

將這幾個類反編譯下: 

  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. }  

反編譯這兩個枚舉類,發(fā)現(xiàn)其中多了一個 $VALUES 數(shù)組,內部包含了所有的枚舉值。

繼續(xù)反編譯測試類: 

  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. }   

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

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

這里我們其實就已經(jīng)知道了,在 switch 語句中,是根據(jù)枚舉元素在枚舉中的序號來轉變成 int 型的。最后再看下測試類的反編譯結果驗證下: 

  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 類型是咋變成 int 類型的?

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

  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. }   

反編譯結果: 

  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. }   

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

  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 是相等的,反編譯結果為: 

  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,對于 hashCode 相等情況通過 equals() 方法判斷,最后再判斷 var3 的值。另外,關注公眾號Java技術棧,在后臺回復:面試,可以獲取我整理的 Java 系列面試題和答案,非常齊全。

四、它們的包裝類型支持嗎?

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

  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. }   

反編譯結果為: 

  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. }   

可以看到,是支持包裝類型的,通過自動拆箱解決。

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

答案是 NPE,畢竟實際還是包裝類型的拆箱,自然就報空指針了。

另外,關注公眾號Java技術棧,在后臺回復:面試,可以獲取我整理的 Java 系列面試題和答案,非常齊全。 

 

責任編輯:龐桂玉 來源: Java技術棧
相關推薦

2021-01-22 15:31:47

JavaSwitchString

2020-10-09 06:48:19

Pythonswitch語句

2021-10-27 07:15:36

Go 循環(huán)引用

2020-07-22 08:01:41

Python開發(fā)運算符

2021-04-20 19:23:07

語法switch-casePython

2021-12-09 10:51:47

Go繼承

2021-12-15 07:49:22

Go語言設計

2023-01-28 08:05:32

轉換Go泛型

2021-07-13 08:09:34

微博推特評論

2024-01-01 08:10:40

Go語言map

2024-01-05 08:45:35

Go語言map

2024-05-28 08:55:52

2011-12-09 20:28:50

2009-03-12 08:42:38

AndroidWMMTK

2021-06-11 00:03:31

鴻蒙智能手機

2021-11-08 11:02:01

Go函數(shù)重載

2021-08-02 09:31:20

Python工具代碼

2009-03-11 17:32:22

聯(lián)發(fā)科WMAndroid

2014-06-05 15:16:49

Linux開源Flash

2024-03-08 08:51:59

Gomain函數(shù)
點贊
收藏

51CTO技術棧公眾號