問題
Javaにおけるラベルは通常、ループ文(do文、for文、while文)に付けられる。
LOOP1:for (String str1 : list1) { // ラベルを付けたfor文
for (String str2 : list2) {
if (str1.equals(str2)) {
found(str1);
break LOOP1; // 外側のforから抜ける
}
}
}
それでは、ループ文以外の文にラベルを付けることはできるか?
- ループ文以外の文にラベルを付けることはできない(コンパイルエラーになる)。
- ループ文以外の文にラベルを付けられる場合もあるが、そのラベルを参照する文が書けないので結局無意味である。
- ループ文以外の文にラベルを付けられる場合があり、かつ、そのラベルを参照する文が書ける場合もある。
正解
3. ループ文以外の文にラベルを付けられる場合があり、かつ、そのラベルを参照する文が書ける場合もある。
解説
Javaのほとんどの文にはラベルを付けられる。
// ラベル付式文!
FOO: a = 42; // OK
// ラベル付if文!
BAR: if (a > 0) b = 1;
else b = -1; // OK
※ただし変数宣言文などラベルが付けられない文もある1。
// ラベル付変数宣言文??
FOO: int a = 42; // NG!
そして、ブロック文およびブロック文を従属させた制御文(ループに限らず、if文やtry文等も含む)にラベル(例えば LABEL:
)が付けられた場合、そのブロックの中で break LABEL;
を実行することで LABEL:
を付けた文から脱出することができる。
FOO: if (val > 1000) { // ラベル付if文!
big = true;
if (val % 2 == 0) break FOO; // ブロックを抜ける
bigOdd = true;
}
例えば、関数の中の特定の領域に対して“早期脱出”をしたい、という場面で活用できるだろう。
BLOCK:{ // 素のブロック
Foo foo1 = stor.findFoo(fooName1);
if (foo1 == null)
break BLOCK; // ブロックを抜ける
Foo foo2 = stor.findFoo(fooName2);
if (foo2 == null)
break BLOCK; // ブロックを抜ける
foo2.setBar(foo1.getBar());
// 以降処理が延々と続く...
}
補足
- ラベル無しのbreak文の対象になるのはループ文とswitch文に限られる。
- continue文の対象になるのは、ラベルの有無に関わらず、ループ文に限られる。
蛇足
実は、ブロックのない文に付けたラベルであっても、それを参照するbreak文は書ける、らしい。
FOO: break FOO; // OK!!!!
まあ、全く有用性はないのだが……。
-
Java言語仕様にある形式定義において、“Statement”に相当する文にラベルが付けられる。局所変数宣言文(“LocalVariableDeclarationStatement”)は“Statement”の一種ではない。 ↩