当前位置:首页 > 开发 > 编程语言 > Java > 正文

Java Switch语句及性能剖析

发表于: 2013-01-29   作者:aubdiy   来源:转载   浏览次数:
摘要: Java Switch语句及性能剖析(转载补充)   一、基本用 switch的case语句可以处理int,short,byte,char类型的值,但是不能处理long,String等类型。 因为short,byte,char都会转换成int进行处理,这一点也可以从生成的字节码看出。 char a = 'e'; &nb

Java Switch语句及性能剖析(转载补充)

 

一、基本用
switch的case语句可以处理int,short,byte,char类型的值,但是不能处理long,String等类型。
因为short,byte,char都会转换成int进行处理,这一点也可以从生成的字节码看出。
  1. char a = 'e';  
  2. switch (a) {  
  3.     case 'c':  
  4.         System.out.println("In case c");  
  5.         break;  
  6.     case 'd':  
  7.         System.out.println("In case d");  
  8.         break;  
  9.     default:  
  10.         System.out.println("In default");  
  11.         break;  
  12.     case 'e':  
  13.         System.out.println("In case e");  
  14.         break;  
  15. }  
   0:    bipush  101
   2:   istore_1
   3:   iload_1
   4:   tableswitch{ //99 to 101
                99: 32;
                100: 43;
                101: 65;
                default: 54 }
生成的字节码始终为bipush或iconst(小于5的整数),用于将整数压入栈。 
二、新特性
在JDK 5中加入的枚举Enum类型也是可以作为case值的。
  1. Type t = Type.C;  
  2. switch (t) {  
  3.     case A:  
  4.         System.out.println("In case A");  
  5.         break;  
  6.     case B:  
  7.         System.out.println("In case B");  
  8.         break;  
  9.     default:  
  10.         System.out.println("In default");  
  11.         break;  
  12.     case C:  
  13.         System.out.println("In case C");  
  14.         break;  
  15. }  
   0:   getstatic       #18; //Field com/cdai/jdk/Type.C:Lcom/cdai/jdk/Type;
   3:   astore_1
   4:   invokestatic    #24; //Method $SWITCH_TABLE$com$cdai$jdk$Type:()[I
   7:   aload_1
   8:   invokevirtual   #27; //Method com/cdai/jdk/Type.ordinal:()I
   11:  iaload
   12:  tableswitch{ //1 to 3
                1: 40;
                2: 51;
                3: 73;
                default: 62 }
从字节码可以看出,对于枚举类型也是调用它的ordinal方法转成整型后进行switch匹配的。
在JDK 7中,又加入了对String类型的支持,从此不用再写If-Else来判断字符串了。
三、两种字节码
switch语句有两种编译结果:
当case中的值连续时,编译成tableswitch,解释执行时从table数组根据case值计算下标来取值,从数组中取到的
便是要跳转的行数。
[java]  view plain copy
  1. int a = 1;  
  2. switch (a) {  
  3.     case 2:  
  4.         System.out.println("In case 2");  
  5.         break;  
  6.     case 3:  
  7.         System.out.println("In case 3");  
  8.         break;  
  9.     default:  
  10.         System.out.println("In default");  
  11.         break;  
  12.     case 1:  
  13.         System.out.println("In case 1");  
  14.         break;  
  15. }  
   0:   iconst_1
   1:   istore_1
   2:   iload_1
   3:    tableswitch{ //1 to 3
                1: 61;
                2: 28;
                3: 39;
                default: 50 }

   28:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   31:  ldc     #22; //String In case 2
   33:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   36:  goto    69
   39:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   42:  ldc     #30; //String In case 3
   44:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   47:  goto    69
   50:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   53:  ldc     #32; //String In default
   55:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   58:  goto    69
   61:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   64:  ldc     #34; //String In case 1
   66:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
当case中的值不连续时,编译成lookupswitch,解释执行时需要从头到尾遍历找到case对应的代码行。
因为case对应的值不是连续的,如果仍然用表来保存case对应的行号,会浪费大量空间。
[java]  view plain copy
  1. int a = 10;  
  2. switch (a) {  
  3.     case 2:  
  4.         System.out.println("In case 2");  
  5.         break;  
  6.     case 3:  
  7.         System.out.println("In case 3");  
  8.         break;  
  9.     default:  
  10.         System.out.println("In default");  
  11.         break;  
  12.     case 10:  
  13.         System.out.println("In case 10");  
  14.         break;  
  15. }  
   0:   bipush  10
   2:   istore_1
   3:   iload_1
   4:    lookupswitch{ //3
                2: 40;
                3: 51;
                10: 73;
                default: 62 }

   40:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   43:  ldc     #22; //String In case 2
   45:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   48:  goto    81
   51:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   54:  ldc     #30; //String In case 3
   56:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   59:  goto    81
   62:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   65:  ldc     #32; //String In default
   67:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   70:  goto    81
   73:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   76:  ldc     #34; //String In case 10
   78:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
由此可以看出,这两种编译结果是编译器在考虑空间占用情况下,对代码效率进行的优化。
另外需要注意一点,就是不管是tableswitch还是lookupswitch,default标签都放在最后进行匹配,
但下面各个case和default语句块的顺序是与源代码相同的。所以尽管default标签没有放在最后,
但它仍然是最后被匹配的。

 

 个人补充:
由于现在的机器性能强劲, 系统的瓶颈更多是IO/DB等,一般不是if else 或者switch,mysql jdbc dirver源码中,
查询结果集resultSet.getObject("aaa")的时候使用的就是if else,
但是个人认为switch代码会使程序易读,易维护

 原帖地址:http://blog.csdn.net/dc_726/article/details/7723497

 

 

Java Switch语句及性能剖析

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
TPTP(Test & Performance Tool Platform)是Eclipse的又一测试/性能剖析的力作,本篇重点关注远程JVM
TPTP(Test & Performance Tool Platform)是Eclipse的又一测试/性能剖析的力作,本篇重点关注远程JVM
TPTP(Test & Performance Tool Platform)是Eclipse的又一测试/性能剖析的力作,本篇重点关注远程JVM
TPTP(Test & Performance Tool Platform)是Eclipse的又一测试/性能剖析的力作,本篇重点关注远程JVM
switch语言句是程序选择结构中的多分支选择结构。 switch语句专用于实现多分支结构程序,特点是各分
日常工作中,处理数据难免会遇到遍历,for循环可能是我们用的比较多的了。本节就来探讨下for语句嵌
JVM本身提供了一组管理的API,通过该API,我们可以获取得到JVM内部主要运行信息,包括内存各代的数
Sun JVM Attach API是Sun JVM中的一套非标准的可以连接到JVM上的API,从JDK6开始引入,除了Solaris
Eclipse Memory Analyzer是一个非常棒的堆内存分析工具,是JDK自带的堆分析工具jhat的一个非常好的
JVM本身提供了一组管理的API,通过该API,我们可以获取得到JVM内部主要运行信息,包括内存各代的数
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号