在C系风格的代码中,标签是一个容易掌握但是却很难熟练使用的特性,容易主要体现在其规则简单,配合goto很容易就能实现一些比较复杂的逻辑。很难熟练使用主要是体现在对于复杂场景下,不好对流程把控,调试,也不好维护,是典型的面向过程的特性。
前两天在看jdk源码的时候,无意中看到线程池中这个方法的源码:
1 private boolean addWorker(Runnable firstTask, boolean core) {
2 retry:
3 for (int c = ctl.get();;) {
4 // Check if queue empty only if necessary.
5 if (runStateAtLeast(c, SHUTDOWN)
6 && (runStateAtLeast(c, STOP)
7 || firstTask != null
8 || workQueue.isEmpty()))
9 return false;
10
11 for (;;) {
12 if (workerCountOf(c)
13 >= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))
14 return false;
15 if (compareAndIncrementWorkerCount(c))
16 break retry;
17 c = ctl.get(); // Re-read ctl
18 if (runStateAtLeast(c, SHUTDOWN))
19 continue retry;
20 // else CAS failed due to workerCount change; retry inner loop
21 }
22 }
23 .....
我一开始以为标签是配合goto 用的,但是仔细一看没有goto 字段,是配合 break,continue来使用的。
详细查了下这个特性,其实很简单。主要是在代码块来使用,总体来说存在两种使用场景
场景一:
在普通代码块中,配合break关键字使用:
在代码块前边声明一个标签,当执行代码块时,如果发现需要提前结束代码块,(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )直接break 标签即可。
普通代码块既可以是 {} 直接包裹的方法,也可以是if/else 语句的代码块
依次来看这几个例子
(1)普通代码块
1 public class Label1 {
2 static int i = 1;
3
4 public static void main(String[] args) {
5 step1:
6 {
7 i++;
8 if (i == 2) {
9 break step1;
10 }
11 i = 3;
12 }
13 System.out.println("i is :" + i);
14 }
15 }
输出结果如下:
i is :2
(2)if代码块
1 public class Label2 {
2 static int i = 0;
3 public static void main(String[] args) {
4 i++;//i = 1
5 step2:
6 if (i != 0) {
7 i++;
8 if (i == 2) {
9 break step2;
10 }
11 i = 3;
12 }
13 System.out.println("i is :" + i);
14 }
15 }
输出结果如下:
i is :2
(3)else 代码块
public class Label3 {
static int i = 1;
public static void main(String[] args) {
i++;
if (i == 0) {
i = 10;
} else step3:{
i++;
if (i == 3) {
break step3;
}
i = 5;
}
System.out.println("i is :" + i);
}
}
输出结果如下:
i is :3
以前看有人些写的代码,喜欢使用这种伪代码块(或者叫做业内常叫「伪块 / 一次性代码块) ,其实都一个意思
do {
//do sth
} while (false);
然后通过break来随时控制,do sth内部的逻辑来提前结束,其实大可不必。只要用标签加普通代码块的格式即可简单实现易读易理解的代码了。
场景二:
在标签关联的循环中,配合break/continue 来操作。我们知道如果在多层循环,(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )内循环想直接退出外层循环,或者直接重新开始外层循环是很繁琐的。但是配合标签,就好处理的多了。
我们以do while加while来举例子:
public class Label4 {
public static void main(String[] args) {
int i = 100;
step4:
do {
while (true) {
if (i <= 105) {
i++;
System.out.println("current i is" + i);
continue step4;
}
i = i + 100;
System.out.println("current i is" + i);
if (i > 300) {
break step4;
}
i--;
}
} while (true);
}
}
输出结果如下:
current i is101
current i is102
current i is103
current i is104
current i is105
current i is106
current i is206
current i is305