Java标签跳转实用小技巧
Java标签跳转的核心就是给循环起个名字,配合带标签的 break 和 continue,直接跳出多层嵌套,不用再靠布尔标志位一层层传。 它在二维数组查找、矩阵遍历这类场景里特别省事,属于那种“知道的人少、用起来真香”的技巧。
在C系风格的代码中,标签是一个容易掌握但是却很难熟练使用的特性,容易主要体现在其规则简单,配合goto很容易就能实现一些比较复杂的逻辑。很难熟练使用主要是体现在对于复杂场景下,不好对流程把控,调试,也不好维护,是典型的面向过程的特性。
前两天在看jdk源码的时候,无意中看到线程池中这个方法的源码:
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (int c = ctl.get();;) {
// Check if queue empty only if necessary.
if (runStateAtLeast(c, SHUTDOWN)
&& (runStateAtLeast(c, STOP)
|| firstTask != null
|| workQueue.isEmpty()))
return false;
for (;;) {
if (workerCountOf(c)
>= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateAtLeast(c, SHUTDOWN))
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
.....我一开始以为标签是配合goto 用的,但是仔细一看没有goto 字段,是配合 break,continue来使用的。
详细查了下这个特性,其实很简单。主要是在代码块来使用,总体来说存在两种使用场景
场景一:
在普通代码块中,配合break关键字使用:
在代码块前边声明一个标签,当执行代码块时,如果发现需要提前结束代码块,(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )直接break 标签即可。
普通代码块既可以是 {} 直接包裹的方法,也可以是if/else 语句的代码块
依次来看这几个例子
(1)普通代码块
public class Label1 {
static int i = 1;
public static void main(String[] args) {
step1:
{
i++;
if (i == 2) {
break step1;
}
i = 3;
}
System.out.println("i is :" + i);
}
}输出结果如下:
i is :2
(2)if代码块
public class Label2 {
static int i = 0;
public static void main(String[] args) {
i++;//i = 1
step2:
if (i != 0) {
i++;
if (i == 2) {
break step2;
}
i = 3;
}
System.out.println("i is :" + i);
}
}输出结果如下:
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
⚠️ 几个容易踩的坑
- 标签作用域:标签只在其声明的那条语句及其子语句内部可见,
break标签名必须在标签声明的作用域内,否则编译报undefined label。 -
break可以作用于任意带标签的语句(包括普通代码块),但 continue只能作用于带标签的循环。 - 标签名大小写敏感:
Outer:和outer:是两个不同的标签。 - 标签不会改变变量作用域,也不影响
finally的执行顺序——哪怕break outer跳出了带finally的循环,对应的finally仍会正常执行。
在 Java 8 的
forEach(Stream)循环里,break和continue都不允许使用,return的效果等同于普通for循环里的continue,只能跳过本次迭代,不能直接结束整个方法。 这种情况还是用传统的 for 循环配合标签更靠谱。
📝 一句话总结
带标签的 break 是“点名跑路”,直接退出整个外层结构;带标签的 continue 是“跳过外层这一轮”,直接进入下一轮。 别再写一堆布尔标志变量了,这是官方原生功能,干净还不容易错。
到此这篇关于Java标签跳转:一个鲜为人知但却很实用的小技巧的文章就介绍到这了,更多相关Java标签跳转内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Java8新特性之Base64详解_动力节点Java学院整理
这篇文章主要为大家详细介绍了Java8新特性之Base64的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-06-06
Spring Boot 3.x 整合Swagger的示例教程
本文给大家介绍Spring Boot 3.x 整合Swagger的示例教程,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧2025-06-06
Spring Boot中KafkaListener的介绍、原理和使用方法案例详解
本文介绍了Spring Boot中 @KafkaListener 注解的介绍、原理和使用方法,通过本文的介绍,我们希望读者能够更好地理解Spring Boot中 @KafkaListener 注解的使用方法,并在项目中更加灵活地应用2023-09-09


最新评论