LoginSignup
9

More than 5 years have passed since last update.

ループ以外の文にラベルは付けられるか?

Last updated at Posted at 2016-12-19

問題

Javaにおけるラベルは通常、ループ文(do文、for文、while文)に付けられる。

LOOP1:for (String str1 : list1) { // ラベルを付けたfor文
    for (String str2 : list2) {
        if (str1.equals(str2)) {
            found(str1);
            break LOOP1; // 外側のforから抜ける
        }
    }
}

それでは、ループ文以外の文にラベルを付けることはできるか?

  1. ループ文以外の文にラベルを付けることはできない(コンパイルエラーになる)。
  2. ループ文以外の文にラベルを付けられる場合もあるが、そのラベルを参照する文が書けないので結局無意味である。
  3. ループ文以外の文にラベルを付けられる場合があり、かつ、そのラベルを参照する文が書ける場合もある。

jaba-2.png

正解

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!!!!

まあ、全く有用性はないのだが……。


  1. Java言語仕様にある形式定義において、“Statement”に相当する文にラベルが付けられる。局所変数宣言文(“LocalVariableDeclarationStatement”)は“Statement”の一種ではない。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9