我们知道JavaSwitch支持byte、short、int类型,在JDK1。5时,支持了枚举类型,在JDK1。7时,又支持了String类型。那么它为什么就不能支持long类型呢,明明它跟byte、short、int一样都是数值型,它又是咋支持String类型的呢?一、结论 不卖关子,先说结论: switch底层是使用int型来进行判断的,即使是枚举、String类型,最终也是转变成int型。由于long型表示范围大于int型,因此不支持long类型。 下面详细介绍下各个类型是如何被转变成int类型的,使用的编译命令为javac,反编译网站为:http:javare。cn二、枚举类型是咋变成int类型的? 在没有实验之前,我想当然的认为它是不是根据枚举的int型字段来计算的(因为一般枚举都是一个int型,一个string型),但是转念一想,万一枚举没有int型字段呢,万一有多个int型字段呢,所以肯定不是这样的,下面看实验吧。 定义两个枚举类,一个枚举类有一个int型属性,一个string型属性,另外一个枚举类只有一个string属性:publicenumSexEnum{MALE(1,男),FEMALE(0,女);privateinttype;privateStringname;SexEnum(inttype,Stringname){this。typetype;this。namename;}}publicenumSex1Enum{MALE(男),FEMALE(女);privateStringname;Sex1Enum(Stringname){this。namename;}} 然后编写一个测试类,并且让两个枚举switch的FEMALE和MALE对应的返回值不同:publicclassSwitchTest{publicintenumSwitch(SexEnumsex){switch(sex){caseMALE:return1;caseFEMALE:return2;default:return3;}}publicintenum1Switch(Sex1Enumsex){switch(sex){caseFEMALE:return1;caseMALE:return2;default:return3;}}} 将这几个类反编译下:SexEnum。classpublicenumSexEnum{MALE(1,男),FEMALE(0,女);privateinttype;privateStringname;FF:syntheticfieldprivatestaticfinalSexEnum〔〕VALUESnewSexEnum〔〕{MALE,FEMALE};privateSexEnum(intvar3,Stringvar4){this。typevar3;this。namevar4;}}Sex1Enum。classpublicenumSex1Enum{MALE(男),FEMALE(女);privateStringname;FF:syntheticfieldprivatestaticfinalSex1Enum〔〕VALUESnewSex1Enum〔〕{MALE,FEMALE};privateSex1Enum(Stringvar3){this。namevar3;}} 反编译这两个枚举类,发现其中多了一个VALUES数组,内部包含了所有的枚举值。继续反编译测试类:SwitchTest1。classimportcom。example。express。test。Sex1Enum;importcom。example。express。test。SexEnum;FF:syntheticclassclassSwitchTest1{FF:syntheticfieldstaticfinalint〔〕SwitchMapcomexampleexpresstestSexEnum;FF:syntheticfieldstaticfinalint〔〕SwitchMapcomexampleexpresstestSex1Enumnewint〔Sex1Enum。values()。length〕;static{try{SwitchMapcomexampleexpresstestSex1Enum〔Sex1Enum。FEMALE。ordinal()〕1;}catch(NoSuchFieldErrorvar4){;}try{SwitchMapcomexampleexpresstestSex1Enum〔Sex1Enum。MALE。ordinal()〕2;}catch(NoSuchFieldErrorvar3){;}SwitchMapcomexampleexpresstestSexEnumnewint〔SexEnum。values()。length〕;try{SwitchMapcomexampleexpresstestSexEnum〔SexEnum。MALE。ordinal()〕1;}catch(NoSuchFieldErrorvar2){;}try{SwitchMapcomexampleexpresstestSexEnum〔SexEnum。FEMALE。ordinal()〕2;}catch(NoSuchFieldErrorvar1){;}}} 首先生成了一个名为SwitchTest1。java的链接类,里面定义了两个枚举数组,这两个数组元素添加的顺序完全和测试类中switch类调用的顺序一致。 枚举元素在数组中的下标由ordinal()函数决定,该方法就是返回枚举元素在枚举类中的序号。面试宝典:https:www。yoodb。com 这里我们其实就已经知道了,在switch语句中,是根据枚举元素在枚举中的序号来转变成int型的。最后再看下测试类的反编译结果验证下:SwitchTest。classimportcom。example。express。test。Sex1Enum;importcom。example。express。test。SexEnum;importcom。example。express。test。SwitchTest。1;publicclassSwitchTest{publicintenumSwitch(SexEnumvar1){switch(1。SwitchMapcomexampleexpresstestSexEnum〔var1。ordinal()〕){case1:return1;case2:return2;default:return3;}}publicintenum1Switch(Sex1Enumvar1){switch(1。SwitchMapcomexampleexpresstestSex1Enum〔var1。ordinal()〕){case1:return1;case2:return2;default:return3;}}}三、String类型是咋变成int类型的? 首先我们先知道char类型是如何变成int类型的,很简单,是ASCII码,例如存在switch语句:publicintcharSwitch(charc){switch(c){casea:return1;caseb:return2;default:returnInteger。MAXVALUE;}} 反编译结果为:publicintcharSwitch(charvar1){switch(var1){case97:return1;case98:return2;default:returnInteger。MAXVALUE;}} 那么对于String来说,利用的就是hashCode()函数了,但是两个不同的字符串hashCode()是有可能相等的,这时候就得靠equals()函数了,例如存在switch语句:publicintstringSwitch(Stringss){switch(ss){caseABCDEa123abc:return1;caseABCDFB123abc:return2;casehelloWorld:return3;default:returnInteger。MAXVALUE;}} 其中字符串ABCDEa123abc和ABCDFB123abc的hashCode是相等的,反编译结果为:publicintstringSwitch(Stringvar1){bytevar31;switch(var1。hashCode()){case1554135584:if(var1。equals(helloWorld)){var32;}break;case165374702:if(var1。equals(ABCDFB123abc)){var31;}elseif(var1。equals(ABCDEa123abc)){var30;}}switch(var3){case0:return1;case1:return2;case2:return3;default:returnInteger。MAXVALUE;}} 可以看到它引入了局部变量var3,对于hashCode相等情况通过equals()方法判断,最后再判断var3的值。四、它们的包装类型支持吗? 这里以Integer类型为例,Character和Byte同理,例如存在switch语句:publicintintegerSwitch(Integerc){switch(c){case1:return1;case2:return2;}return1;} 反编译结果为:publicintintegerSwitch(Integervar1){switch(var1。intValue()){case1:return1;case2:return2;default:return1;}} 可以看到,是支持包装类型的,通过自动拆箱解决。 那万一包装类型是NULL咋办,首先我们知道swtich的case是不给加null的,编译都通不过,那如果传null呢? 答案是NPE,毕竟实际还是包装类型的拆箱,自然就报空指针了。