java switch语句探索

1、问题

对于下面的代码:

public class Switch{
	public void test(int i) {
		switch(i) {
			case 0:
			case 1:
				System.out.println("a");
				break;
			case 2:
				System.out.println("a");
				break;
			default:
				break;
		}
	}
}
我们会发现,当i=0的时候,会进入0的case块,并且还继续执行1的case块;当i=2的时候只执行2的case块;当i=3的时候直接执行的是default的case块。很多时候我们不知道这其中的原因是什么,下面就是笔者带领大家深入理解这些东西背后的深层次的原因。

2、反编译上面的代码:

public class Switch {
  public Switch();
    Code:
       0: aload_0       
       1: invokespecial #1;                 // Method java/lang/Object."<init>":()V
       4: return        

  public void test(int);
    Code:
       0: iload_1       
       1: tableswitch   { // 0 to 4
                     0: 36
                     1: 36
                     2: 58
                     3: 69
                     4: 47
               default: 69
          }
      36: getstatic     #2;                 // Field java/lang/System.out:Ljava/io/PrintStream;
      39: ldc           #3;                 // String a
      41: invokevirtual #4;                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      44: goto          69
      47: getstatic     #2;                 // Field java/lang/System.out:Ljava/io/PrintStream;
      50: ldc           #5;                 // String c
      52: invokevirtual #4;                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      55: goto          69
      58: getstatic     #2;                 // Field java/lang/System.out:Ljava/io/PrintStream;
      61: ldc           #3;                 // String a
      63: invokevirtual #4;                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      66: goto          69
      69: return        
}



我们只关注test方法,Code后面的都是反编译出来的字节码,其中每行的开始是字节码在每一个代码块的开始的字节,所以这些数字不会是连续的,为了方便,笔者下面只称这些字节索引值为行。

0行:将本地方法栈的第一个局部加载到操作栈中,第一个参数就是test的方法的参数i,可能有读者会问,那test方法的本地方法栈的第0个局部变量是什么?对于非static的方法,编译器会给方法的插入一个默认的参数,这个参数指向类的实例,其实也就是所谓的this对象,这就是为什么我们在static方法中没有办法使用this,而只能在非static方法中使用的缘故。

1行:在表中查找实际的i值对应的实际的代码入口,从这个代码查找我们可以发现i=0和i=1的时候指向了相同的代码入口,i=2时指向了case 2的代码的入口

36行到69行:我们发现swicth-case语句中的所有的非case语句,都编译到了一起,只有遇到像44行、55行这样的break语句才会跳出,也就是说,如果没有,就会继续往下走,所以说,像下面的语句,遇到case A,会执行do_a也会执行do_b。

case A:
 do_a
case B:
 do_b;
 break;

3、还有一些关于tableswitch的其他东西,比如排序等等,还有稀疏的case情况的处理,以及java 7支持的string的swicth-case,等明天再写,困死了,洗洗睡觉。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值