Java 基础语法 --- Switch

0x01 关键字Switch

在初学编程语言的时候,从C语言开始学起,所有的语言基本都会讲到switch关键字。他是一个用来进行分支判断的关键字,和if的作用类似,但是很多时候,使用switch会更加的优雅并且更加的容易扩展。但是,我依稀的记得,switch关键字并不支持String类型(有待查验)。

但是,不知道从JDK的哪个版本开始,switch关键字开始支持String了。很神奇。

0x02 Switch 基本实现

先来看一段简单的代码:

class TestSwitchInteger {
	public void methodA(int params) {
		switch (params) {
			case 1:
				System.out.println("This is number 1.");
				break;
			case 2:
				System.out.println("This is number 2.");
				break;
			default:
				System.out.println("others number.");
				break;
		}
	}
}

代码很清晰,methodA中,根据params的值来进行输出。我们看一下编译过后的代码是什么样子:

1: lookupswitch  { // 2
               1: 28
               2: 39
         default: 50
    }
28: getstatic     #2  // Field java/lang/System.out:Ljava/io/PrintStream;
39: getstatic     #2  // Field java/lang/System.out:Ljava/io/PrintStream;
50: getstatic     #2  // Field java/lang/System.out:Ljava/io/PrintStream;

这个地方只列出了关键输出,详细内容请自行查看,命令如下:

# javap -v TestSwitchInteger

可以看到,代码被翻译成了lookupswitch, 当输入参数为 1时,执行第28行的输出。

接下来,我们看看String是怎么实现的,先看源码:

public void methodA(String params) {
    switch (params) {
        case "a":
            System.out.println("a");
            break;
        case "b":
            System.out.println("b");
            break;
        default:
            System.out.println("others");
            break;
    }
}

接下来,看看编译过后的结构:

5: invokevirtual #2         // Method java/lang/String.hashCode:()I
8: lookupswitch  { // 2
              97: 36
              98: 50
         default: 61
    }
36: aload_2
37: ldc           #3        // String a
39: invokevirtual #4        // Method java/lang/String.equals:(Ljava/lang/Object;)Z
42: ifeq          61
45: iconst_0
46: istore_3
47: goto          61
50: aload_2
51: ldc           #5        // String b
53: invokevirtual #4        // Method java/lang/String.equals:(Ljava/lang/Object;)Z
56: ifeq          61
59: iconst_1
60: istore_3
61: iload_3
62: lookupswitch  { // 2
               0: 88
               1: 99
         default: 110
    }
88: getstatic     #6         // Field java/lang/System.out:Ljava/io/PrintStream;
91: ldc           #3         // String a
93: invokevirtual #7         // Method java/io/PrintStream.println:(Ljava/lang/String;)V
96: goto          118
99: getstatic     #6         // Field java/lang/System.out:Ljava/io/PrintStream;
102: ldc           #5        // String b
104: invokevirtual #7        // Method java/io/PrintStream.println:(Ljava/lang/String;)V
107: goto          118
110: getstatic     #6        // Field java/lang/System.out:Ljava/io/PrintStream;
113: ldc           #8        // String others
115: invokevirtual #7        // Method java/io/PrintStream.println:(Ljava/lang/String;)V

可以看到,首先会执行 params.hashCode()拿到一个int值,然后去执行 int 的 switch方法,其中 97, 98 分别为a, b的hashCode,然后会分别产生 0, 1 两个基础值,然后在执行一次 switch方法。翻译成Java代码,就是如下情况:

public void methodA(String params) {
	int a = -1;
	switch (params.hashCode()) {
		case "a".hashCode():
			a = 0; 
			break;
			case "b".hashCode():
			a = 1;
		default:
			break;
	}
	switch (a) {
		case 0:
			System.out.println("a");
			break;
		case 1:
			System.out.println("b");				
			break;
		default:
			System.out.println("others");
			break;
	}
}
0x03 思考

有些逻辑在语言层面不支持,我们可以从其它角度来考虑,说不定就能找到解决方案,就比如说上面这个,编译的时候生成特殊的代码以完成对应的逻辑。在java中,还有一个和这个类似,那就是内部类调用外部类的private变量。有兴趣的同学可以去研究一下。

在Android中也有一些库使用了类似的方式,比如说 Butterknife, Dagger 2等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值