Rostislav Krasny
Rostislav Krasny

Reputation: 695

Is a label a Java statement or not?

Is a label a Java statement or not and if a label is a statement where is it defined as a statement in the Java Language Specification?

My question relates to the following reply of Jan Lahoda in the bug report that I've sent to Oracle. I'm unable to discuss it there because I can't get an account in the OpenJDK Jira.

https://bugs.openjdk.java.net/browse/JDK-8211052

In case of e.g.: A: B: while (true) continue A; the statement on which the "continue" is applied is not "while (true) continue A;", but "B: while (true) continue A;", and the spec requires the target for continue is a while/do/for statement, which is not fulfilled here. Hence the compile-time error.

I think a label in Java is not a statement and in Jan's example both the A and the B labels relate to the same while-loop statement and then no compile time error should be triggered.

Addition:

Isn't a labeled while/do/for statement in Java a while/do/for statement?

Upvotes: 4

Views: 284

Answers (2)

luk2302
luk2302

Reputation: 57114

Following the JLS a Statement can be

StatementWithoutTrailingSubstatement
LabeledStatement
IfThenStatement
IfThenElseStatement
WhileStatement
ForStatement

with LabeledStatement being

Identifier : Statement

and stated

The Identifier is declared to be the label of the immediately contained Statement

so in case of a loop like

public void method() {
    loop1: loop2: while (true) {
        if (true) {
            break loop1;
        } else {
            continue loop1;
        }
    }
}

the Statement of the Label loop1 is the entire loop2 ... stuff.

And if we look at the definition of break it is stated that

the break target need not be a switch, while, do, or for statement.

whereas for the continue it states

The continue target must be a while, do, or for statement, or a compile-time error occurs.

These definitions are properly in line with the compiler giving a compiler error for the continue loop1 statement and letting break loop1 be valid since loop2: ... is not a "while, do, or for statement".


Regarding your actual question: Is label a Java statement or not?

The following code is perfectly legal and compiles fine

public void method() {
    loop:;
}

This follows the expansion of Statement -> LabeledStatement -> Identifier : Statement -> loop : Statement -> loop : StatementWithoutTrailingSubstatement -> loop : EmptyStatement ->

loop : ;

No, a label is no statement by itself, an identifier (which is then called "label") plus a column plus an EmptyStatement (;) however is.


Isn't labeled while/do/for statement in Java a while/do/for statement?

No!

A LabeledStatement is exactly that: a LabeledStatement. A labeled while is Statement -> Label -> Identifier : Statement -> Identifier : WhileStatement which is something fundamentally different than Statement -> WhileStatement!

Upvotes: 6

rgettman
rgettman

Reputation: 178263

The JLS, Section 14.16, talks about the continue statement:

The continue target must be a while, do, or for statement, or a compile-time error occurs.

Simple enough, but let's look at the grammar for a labeled statement (Section 14.7).

LabeledStatement:

    Identifier : Statement

It can contain another statements in general, which in turn may be a while, do, or for ("wdf") statement, or another labeled statement (Section 14.5) (or other kinds of statements).

But the label by itself is not a statement; it needs the other statement as part of itself.

Next, nested labeled statements are allowed, so in general you can do something like:

A: B: yourStatementHere;

You can nest it further if you want:

A: B: C: D: E: F: G: yourStatementHere;

However, with

A: B: while (true) continue A;

The statement that A: labels is another labeled statement, not a "wdf" statement, even if the B: labeled statement itself contains a while statement.

If you put on your lawyer hat, you can argue that the sentence above about the continue statement needing to refer to a "wdf" statement says nothing about the "wdf" statement being nested in a labeled statement, so it should be a compiler error.

That seems very picky to me; perhaps the JLS should have had a clause indicating that the "wdf" statement could be itself nested in a labeled statement.

But until that happens, this appears to be a correct, if unintended, consequence of the wording the JLS provides, quoted above.

So why is break allowed to do this?

A: B: while (true) break A;  // no error

There is no corresponding line in Section 14.15 of the JLS, which talks about the break statement, that enforces that the target of a break statement must be a "wdf" statement. A break statement must still be within a "wdf" statement (or a switch statement), but there is no corresponding requirement that its label refer to a specific kind of statement.

Upvotes: 3

Related Questions