Following compiles without any errors:
class App {
boolean b;
boolean c;
void foo(List<Integer> ints) {
myLabel:
for (Integer i : ints) {
while (!b) {
if (c) {
continue myLabel;
}
}
};
}
}
But if I modify foo
as follows:
void foo(List<Integer> ints) {
myLabel:
ints.forEach(integer -> {
while (!b) {
if (c) {
continue myLabel;
}
}
});
}
I get Error:(17, 21) undefined label: myLabel
What is the difference? As far as I know, the new forEach
is just a shortcut for the enhanced for loop?
As stated in the comments, forEach
is just a method invocation. The snippet
myLabel: ints.forEach(integer -> ...);
is a labeled statement:
identifier statement labels are used with
break
orcontinue
statements (§14.15, §14.16) appearing anywhere within the labeled statement.
To repeat, the labeled statement is the method invocation expression. Your continue
statement is not within the labeled statement.
Your continue
statement is within a while
statement appearing within the body of a lambda expression.
A
continue
statement with labelIdentifier
attempts to transfer control to the enclosing labeled statement (§14.7) that has the sameIdentifier
as its label; that statement, which is called the continue target, then immediately ends the current iteration and begins a new one.[...]
The continue target must be a
while
,do
, orfor
statement, or a compile-time error occurs.A
continue
statement must refer to a label within the immediately enclosing method, constructor, initializer, or lambda body. There are no non-local jumps. If no labeled statement withIdentifier
as its label in the immediately enclosing method, constructor, initializer, or lambda body contains the continue statement, a compile-time error occurs.
Since there is no labeled (while
, do
, or for
) statement named myLabel
in the immediately enclosing lambda body, you get a compile-time error.