Java标签跳转:一个鲜为人知但却很实用的小技巧

在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

 

posted @ 2026-09-24 19:16  王若伊_恩赐解脱  阅读(26)  评论(1)    收藏  举报