• 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
    复制代码

     

  • 相关阅读:
    .NET 8 Web开发入门(四):注入燃料——Entity Framework Core 与 Code First 实战
    Java多线程探究【三线程同步】
    shell脚本
    通过包管理器方式安装 Node.js
    学习笔记-接口测试(postman、jmeter)
    什么是网络变压器,它是干什么用的?作用/参数表/价格及型号体系有哪些?怎么测量网络变压器好坏
    【Android开发】学习笔记(一)
    【004】Shell脚本以怎样的方式执行?
    【无标题】
    【机器学习】阿里云天池竞赛——工业蒸汽量预测(3)
  • 原文地址:https://www.cnblogs.com/jilodream/p/23115325