记得曾经去一家公司面试,那时啥也不懂,面试我的那个人好像呆过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)在编程语言中是一种非常有用的数据类型,它允许我们定义一组相关的命名常量,便于代码的可读性和维护。在C#中,枚举是通过`enum`关键字来创建的。在给定的示例中,`BoxType`枚举定义了三种箱型:...
在编程世界中,`enum`(枚举)和`switch`语句是C++和许多其他编程语言中的关键构造,用于提高代码可读性和效率。本文将深入探讨这两个概念,并结合VC++(Visual C++)环境下的实际案例,提供一个6页的详细分析。 ...
在Java编程语言中,`enum`(枚举)和`switch`语句是两个非常重要的概念,它们在软件开发中有着广泛的应用。本教程将深入探讨这两个知识点,并通过实例源代码帮助你理解它们的用法。 `enum`是Java中的一个特殊的类...
Java枚举类型(Enum)是Java SE 5.0引入的一种新的数据类型,它为开发者提供了更为强大且安全的方式来表示一组常量。枚举在Java中不仅是一个类,还是一种特殊的类型,允许我们定义自己的常量集合。接下来,我们将...
在 JDK 1.6 之前,switch 语句只支持 `int`、`char` 和 `enum` 类型。使用 enum,可以让我们的代码可读性更强。例如: ```java enum Signal { GREEN, YELLOW, RED } public class TrafficLight { Signal color = ...
### C++中的枚举类型(Enum) 在C++编程语言中,枚举(`enum`)是一种用户定义的...总之,枚举类型是C++中非常实用的数据类型之一,它不仅可以提高代码的可读性和可维护性,还能帮助开发者更直观地管理有限的选项集。
### Enum的深度解析与应用技巧 #### 一、Enum的本质与特性 `Enum`,作为Java语言中的一个关键字,自JDK 5.0引入以来,便赋予了开发者一种全新的数据类型——枚举类型,其设计初衷在于为编程提供更安全、更简洁的...
switch (this) { case RED: if ("红色".equals(name)) {this.name = name;} break; case GREEN: if ("绿色".equals(name)) {this.name = name;} break; case BLUE: if ("蓝色".equals(name)) {this.name = name;...
switch (this) { case SATURDAY: return MONDAY; case SUNDAY: return MONDAY; default: return values()[ordinal() + 1]; } } } ``` 这里,`nextWorkingDay()`方法根据当前枚举值返回下一个工作日。`...
在编程领域,枚举(Enum)是一种非常常见且实用的数据类型,它用于定义一组相关的常量。枚举常被用来表示一组预定义的值,这些值通常代表某种特定的分类或者状态。在Java、C#等面向对象的语言中,枚举(Enum)是语言...
Java中的枚举(enum)类型是在JDK 1.5版本引入的一个强大的特性,它用于定义一组相关的常量。在C/C++等语言中,枚举通常用来表示一组具有固定值的常量集合,但在Java中,枚举不仅限于此,它提供了更多的功能和灵活性...
在Java中,`switch`语句最初只能处理`int`、`char`以及`enum`类型的数据。然而,在实际开发过程中,有时需要根据字符串(`String`)来执行不同的逻辑分支。为了解决这一问题,Java 7引入了一个新特性——支持直接在`...
Objective-C的`switch`语句可以比较的不仅是整型常量,还可以是枚举类型(`enum`)或者字符串(`NSString`)。例如: ```objc typedef enum { ColorRed, ColorGreen, ColorBlue } Color; Color color = Color...
首先,"switch"语句可以与枚举类型(enum)一起使用,这是.NET框架的一个特性。枚举类型提供了强类型和可读性,使得代码更加结构化。例如: ```cpp enum Color { Red, Green, Blue }; Color myColor = Color::Green...
### 枚举类型在switch语句中的用法 在编程语言中,枚举(Enum)是一种数据类型,它由一组固定的常量组成,通常用于表示有限的预定义值...总之,正确使用枚举类型和`switch`语句是编写高质量、可维护的代码的关键之一。
在`TestEnum`这个示例程序中,可能会演示如何声明、初始化枚举、枚举变量的使用,以及与之相关的各种操作。可能还会涉及枚举成员的遍历,例如通过`foreach`循环。此外,可能还会展示如何处理枚举的Flags特性,这在...
枚举(enum)在编程语言中是一种非常常见且实用的数据类型,它用于定义一组相关的命名常量。在C#中,枚举(enum)是一种强类型的数据结构,它基于整数类型,如int、byte、short等。枚举提供了一种更加清晰、可读性更...