发现
今天在探索线程池实现原理的时候,遇到一个重来没有见过的语法,通过网上查阅资料,自己也做了验证
验证
通过查阅资料,retry其实就是一个标记,标记对一个循环的操作(continue和bread)处理点,功能类似于goto,所以retry一般都是伴随着for循环出现,retry: 标记的下一行就是for循环,在for循环里面调用continue或者break 再紧接着retry标记时,就表示从这个地方开始执行continue或者break操作
1. 普通循环结果
public static void testContinue() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
System.out.print(j + ",");
}
}
System.out.println();
}
// 输出结果:0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,
2. 普通break
public static void testContinue() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
System.out.print(j + ",");
if (j == 3) {
break;
}
}
}
System.out.println();
}
// 输出结果:0,1,2,3,0,1,2,3,0,1,2,3,
3. retry标记continue
public static void testContinue() {
cmlx:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
System.out.print(j + ",");
if (j == 3) {
continue cmlx;
}
}
System.out.println();
}
}
// 输出结果:0,1,2,3,0,1,2,3,0,1,2,3,
4. retry标记break
public static void testContinue() {
cmlx:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
System.out.print(j + ",");
if (j == 3) {
break cmlx;
}
}
System.out.println();
}
}
// 输出结果:0,1,2,3,
结论
经过上面的demo联系,在内层循环里面调用continue(或者break)后接着retry标识符,程序直接转到最外层for循环去处理了,且发现 retry标记continue
和 普通break
实现的效果是一样的,retry只是一个标记,可以随意命名,这里用的是cmlx。
反编译验证结论
// 反编译前
public static void testContinue() {
cmlx:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
System.out.print(j + ",");
if (j == 3) {
continue cmlx;
}
}
System.out.println();
}
}
public static void testBreak() {
cmlx:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
System.out.print(j + ",");
if (j == 3) {
break cmlx;
}
}
}
}
public static void testBreak1() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
System.out.print(j + ",");
if (j == 3) {
break;
}
}
}
}
// 反编译后
public static void testContinue() {
block0: for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 5; ++j) {
System.out.print(j + ",");
if (j == 3) continue block0;
}
System.out.println();
}
}
public static void testBreak() {
block0: for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 5; ++j) {
System.out.print(j + ",");
if (j == 3) break block0;
}
}
}
public static void testBreak1() {
block0: for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 5; ++j) {
System.out.print(j + ",");
if (j == 3) continue block0;
}
}
}
// 其他博主反编译之后的代码
public static void testContinue()
{
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++)
{
System.out.print(j + ", ");
if (j == 3) {
break;
}
}
}
System.out.print(" >>> OK");
}
public static void testBreak()
{
label59:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++)
{
System.out.print(j + ", ");
if (j == 3) {
break label59;
}
}
}
System.out.print(" >>> OK");
}
可能是反编译工具的不同,我这边使用cfr(http://www.benf.org/other/cfr/)反编译出来的代码和其他博主反编译出来的不一样。但是得出来的结论是一样的。
启发
虽然我们平时没见过这种写法,但是类似跳出多重循环的场景却不在少数,一般我们跳出多重循环会怎么处理
- 跳出里面的for循环,继续从外面for循环开始执行:
public static void testContinueR() {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 5; j++) {
System.out.print(j + ", ");
if(j == 3) {
break;
}
}
}
}
- 跳出里外两层循环,直接往下执行逻辑:
public static void testBreakR() {
boolean flag = false;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 5; j++) {
System.out.print(j + ", ");
if(j == 3) {
flag = true;
break;
}
}
if(flag) {
break;
}
}
System.out.println(" >>> OK");
}
扩展
标签还可以定义在三种循环 (for() {}, do{} while(), while() {}) 的开始位置,功能就是跳出多出循环