记得曾经去一家公司面试,那时啥也不懂,面试我的那个人好像呆过IBM,数据结构、编译原理这些都很NB。
问答环节
他:java switch中能支持什么类型?
我:byte short char int ,jdk1.5出来了enum,同样也支持enum
他:为什么能支持byte short char int 而long不行?
我:这个可能是设计问题
他:其实jvm执行class文件的时候,byte short char int这些都是当int类型来执行的,long不能直接转换成int,编译阶段就通不过了。
我:我那个时候不太理解他说的那个意思,只能点点头
他:好,那接着讨论switch为什么支持enum,刚才也讨论过switch其实都是int类型,也只支持int,那enum不是int类型,是个对象,那为什么支持呢!
我:那个时候我就蒙了(心里想着,你这家伙,就胡扯),但我讲不出理由,就直接说不知道
他:其实在switch中enum也是int类型
我:心想----我不知道你说的是对还是错,你怎么说都行
自从那以后,哥去研究虚拟机,java指令
好,废话不多说了,现在来看一下代码,代码比较简单!
/*************************************
*************************************
源代码
*************************************
*************************************/
public static void testSwitchInt() {
int intElement = 3;
switch (intElement) {
case 3:
System.out.println("3");
break;
default:
System.out.println("int DEFAULT");
break;
}
}
//int 类型反编译跟源代码是一样的
/*************************************
*************************************
用javap工具看class指令
*************************************
*************************************/
//case 的值本来就是int,这没什么好说的
public static void testSwitchInt();
Code:
Stack=2, Locals=1, Args_size=0
0: iconst_3 //解释:加载int常量3
1: istore_0 //解释:保存int类型到局部变量表index为0的位置(其实保存的就是3)
2: iload_0 //加载局部变量表index为0的位置的int变量,用于switch里面
3: lookupswitch{ //1
3: 20;
default: 31 }
20: getstatic #9; //Field java/lang/System.out:Ljava/io/PrintStream;
23: ldc #13; //String 3
25: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
28: goto 39
31: getstatic #9; //Field java/lang/System.out:Ljava/io/PrintStream;
34: ldc #14; //String int DEFAULT
36: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
39: return
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
/*************************************
*************************************
源代码
*************************************
*************************************/
public static void testSwitchChar() {
int charElement = 'a'; //ascii对应的是97,编译器直接把这个值编译成97,case里面也是这样的
switch (charElement) {
case 'a':
System.out.println("a");
break;
default:
System.out.println("char DEFAULT");
break;
}
}
/*************************************
*************************************
编译后的代码
*************************************
*************************************/
public static void testSwitchChar()
{
int charElement = 97;
switch(charElement)
{
case 97: // 'a'
System.out.println("a");
break;
default:
System.out.println("char DEFAULT");
break;
}
}
/*************************************
*************************************
用javap工具看class指令
*************************************
*************************************/
//case 的值本来就是char类型,但被编译器处理成int
public static void testSwitchChar();
Code:
Stack=2, Locals=1, Args_size=0
0: bipush 97 //解释:加载int常量97,a的ascii码
2: istore_0 //接下来和上面都一样的
3: iload_0
4: tableswitch{ //97 to 97
97: 24;
default: 35 }
24: getstatic #46; //Field java/lang/System.out:Ljava/io/PrintStream;
27: ldc #68; //String a
29: invokevirtual #53; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
32: goto 43
35: getstatic #46; //Field java/lang/System.out:Ljava/io/PrintStream;
38: ldc #70; //String char DEFAULT
40: invokevirtual #53; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
43: return
byte short 也是同理,都会编译成int
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
*************************上面的例子都比较好理解,enum大家可能也会有点疑惑*********************************
/*************************************
*************************************
源代码
*************************************
*************************************/
enum EnumTest {
WINTER, SUMMER, SPRING, AUTUMN;
}
public static void testSwitchEnum() {
EnumTest enumElement = EnumTest.AUTUMN;
switch (enumElement) {
case AUTUMN:
System.out.println("AUTUMN");
break;
default:
System.out.println("enum DEFAULT");
break;
}
}
/*************************************
*************************************
enum类编译后的代码
*************************************
*************************************/
//enum其实也就是个普通的类,继承Enum
public final class EnumTest extends Enum
{
private EnumTest(String s, int i)
{
super(s, i);
/*调用父类的构造函数
protected Enum(String name, int ordinal) {
this.name = name; //名称
this.ordinal = ordinal; 元素位置
}
*/
}
public static EnumTest[] values()
{
EnumTest aenumtest[];
int i;
EnumTest aenumtest1[];
System.arraycopy(aenumtest = ENUM$VALUES, 0, aenumtest1 = new EnumTest[i = aenumtest.length], 0, i);
return aenumtest1;
}
public static EnumTest valueOf(String s)
{
return (EnumTest)Enum.valueOf(meiju/EnumTest, s);
}
public static final EnumTest WINTER;
public static final EnumTest SUMMER;
public static final EnumTest SPRING;
public static final EnumTest AUTUMN;
private static final EnumTest ENUM$VALUES[];
static
{
//enum的位置的排好的,想数组一样,enum元素最终都保存在ENUM$VALUES数组
WINTER = new EnumTest("WINTER", 0);
SUMMER = new EnumTest("SUMMER", 1);
SPRING = new EnumTest("SPRING", 2);
AUTUMN = new EnumTest("AUTUMN", 3);
ENUM$VALUES = (new EnumTest[] {
WINTER, SUMMER, SPRING, AUTUMN
});
}
}
/*************************************
*************************************
testSwitchEnum方法编译后的代码
*************************************
*************************************/
用到enum元素,所以会在当前类中多生成一个$SWITCH_TABLE$meiju$EnumTest()方法和$SWITCH_TABLE$meiju$EnumTest[]变量,用于switch
static int[] $SWITCH_TABLE$meiju$EnumTest()
{
$SWITCH_TABLE$meiju$EnumTest;
if($SWITCH_TABLE$meiju$EnumTest == null) goto _L2; else goto _L1
_L1:
return;
_L2:
JVM INSTR pop ;
int ai[] = new int[EnumTest.values().length];
try
{
ai[EnumTest.AUTUMN.ordinal()] = 4;
}
catch(NoSuchFieldError _ex) { }
try
{
ai[EnumTest.SPRING.ordinal()] = 3;
}
catch(NoSuchFieldError _ex) { }
try
{
ai[EnumTest.SUMMER.ordinal()] = 2;
}
catch(NoSuchFieldError _ex) { }
try
{
ai[EnumTest.WINTER.ordinal()] = 1;
}
catch(NoSuchFieldError _ex) { }
return $SWITCH_TABLE$meiju$EnumTest = ai;
}
private static int $SWITCH_TABLE$meiju$EnumTest[];//保存的是enum的index
public static void testSwitchEnum()
{
EnumTest enumElement = EnumTest.AUTUMN;
//这个就是上面所用到的变量
switch($SWITCH_TABLE$meiju$EnumTest()[enumElement.ordinal()])
{
case 4: // '\004' 因为enum类的元素其实就是个常量,在编译阶段就能确定值,在源代码的case AUTUMN: 其实也就被他所在的ordinal()给替换掉了,其实就是索引
System.out.println("AUTUMN");
break;
default:
System.out.println("enum DEFAULT");
break;
}
}
/*************************************
*************************************
用javap工具看class指令
*************************************
*************************************/
public static void testSwitchEnum();
Code:
Stack=2, Locals=1, Args_size=0
0: getstatic #6; //Field meiju/EnumTest.AUTUMN:Lmeiju/EnumTest;
3: astore_0
4: getstatic #7; //Field meiju/SwitchEnum$1.$SwitchMap$meiju$EnumTest
:[I
7: aload_0
8: invokevirtual #8; //Method meiju/EnumTest.ordinal:()I
11: iaload
12: lookupswitch{ //1
1: 32;
default: 43 }
32: getstatic #9; //Field java/lang/System.out:Ljava/io/PrintStream;
35: ldc #10; //String AUTUMN
37: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
40: goto 51
43: getstatic #9; //Field java/lang/System.out:Ljava/io/PrintStream;
46: ldc #12; //String enum DEFAULT
48: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
51: return
事实证明当时他不是忽悠我,确实是这样的:)
分享到:
相关推荐
自己整理枚举enum和switch 的使用代码
7enum和switch语句联合案例分析VC共6页.pdf.zip
Java 实例 - enum 和 switch 语句使用源代码-详细教程.zip
它也适用于 enumerated types (枚举类型)(在 Enum Types 中讨论),String 类以及一些包装某些原始类型的特殊类:Character,Byte,Short 和 Integer(在 Numbers and Strings 中讨论)。 以下代码示例 SwitchDemo ...
本文实例讲述了PHP中Enum(枚举)用法。分享给大家供大家参考,具体如下: PHP其实有Enum类库的,需要安装perl扩展,所以不是php的标准扩展,因此代码的实现需要运行的php环境支持。 (1)扩展类库SplEnum类。该类的...
JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。 enum Signal { GREEN, YELLOW, RED } public class TrafficLight { Signal color = Signal.RED; public void ...
Swift中通过enum关键字可以直接创建出枚举对象,而且可以使用switch和case语句来进行流程控制,十分强大和灵活,这里我们就来详解Swift中enum枚举类型的用法
auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if while static
long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if static while asm _cs _ds _es _ss cdecl far huge ...
* Fixed ‘Static Switch’ node registering duplicates in the material properties group * Improvements: * Cull, Stencil, Color Mask and Depth options can now reference properties instead of standard...
auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do while static f ...
如果我们在页面上直接输出我们希望匹配的汉语意思或则其他满足我们需求的语句就更好了,当然,通常小伙伴们都会再页面上if(enum==1) “我是一个枚举”或者switch(enum)这种方式解决。 枚举的优点: 枚举可以使...
break:跳出当前循环 else :条件语句否定分支(与 if 连用) switch :用于开关语句 case:开关语句分支 enum :声明枚举类型 register:声明积存器变量 typedef:用以给数据类型取别名 char :声明字符型变量或函数...
自定义Nintendo Switch服务以安装和访问USB驱动器 信息 这个sysmodule将成为Atmosphere的一部分,但是由于缺乏动力,我停止了几个月的研究。 这是尝试移植旧代码并修复可能存在的错误的尝试,并且仍在进行中。 不...
enum Status {UNHOOKED,HOOKED}; enum MenuType {MAINMENU, ADM_SUBMENU, USER_SUBMENU}; enum FuncType {NONE, ADM_MOD, USER_MOD, OPEN_ACCOUNT, REPORT_LOSS, UNHOOKING, CLOSE_ACCOUNT, SAVING, DRAWING, ...
"double", "else", "enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union", ...
是用于管理Angular应用程序状态的功能非常强大的实用程序,但一些开发人员批评该包含过多的样板文件(尤其是在动作类中),并且在reducers中具有较大的switch语句。 是一个分支,该使用封装动作和简化器,从而减少了...
3.9 案例:机会游戏与enum简介 3.10 存储类 3.11 作用域规则 3.12 递归 3.13 使用递归举例:Fibonacci数列 3.14 递归与迭代 3.15 带空参数表的函数 3.16 内联函数 3.17 引用与引用参数 3.18 默认参数 ...
比如,switch 的 NPE 问题、浮点数的比较、无泛型限制、锁的使用方式、判断表达式、日期格式等。 3)修改描述 112 处。比如,IFNULL 的判断、集合的 toArray、日志处理等。 4)完善若干处示例。比如,命名示例、卫...