ラベルステートメント
日本語 | 張り紙命令、付箋命令 |
英語 | label statement |
ふりがな | らべるすてーとめんと |
フリガナ | ラベルステートメント |
break及びcontinueの「移動先」を指定するステートメント。
ステートメントの一種。
「ラベル名:ステートメント」の形式で記述することができる。
「ラベル名:」の後の「ステートメント」(ブロック、forステートメント、whileステートメント等)内で「break ラベル名;」と記述することで、指定したステートメントの直後へと処理が移る。その際、中のブロックのネストは無視される。
また同じく「continue ラベル名;」と指定することで指定したステートメントの「次の周」へと処理を移すことができる。ただし、その際「ステートメント」にはforステートメント及びwhileステートメントの「ループ」を行うステートメントのみ使用できる。
ラベルを使用するということでgotoに似ているが、基本的に「ブロックの外」もしくは「次の周」にしか移動できないため、自由度は低く、その分安全である。
ただし、ラベルを使用しないbreakやcontinueに比べて分かりにくく、ラベルそのものへの抵抗もあるためほとんど使用されることはない。
同じラベルだが、switch内のラベルとは別の分類であるため注意。
ステートメントの一種。
「ラベル名:ステートメント」の形式で記述することができる。
「ラベル名:」の後の「ステートメント」(ブロック、forステートメント、whileステートメント等)内で「break ラベル名;」と記述することで、指定したステートメントの直後へと処理が移る。その際、中のブロックのネストは無視される。
また同じく「continue ラベル名;」と指定することで指定したステートメントの「次の周」へと処理を移すことができる。ただし、その際「ステートメント」にはforステートメント及びwhileステートメントの「ループ」を行うステートメントのみ使用できる。
ラベルを使用するということでgotoに似ているが、基本的に「ブロックの外」もしくは「次の周」にしか移動できないため、自由度は低く、その分安全である。
ただし、ラベルを使用しないbreakやcontinueに比べて分かりにくく、ラベルそのものへの抵抗もあるためほとんど使用されることはない。
同じラベルだが、switch内のラベルとは別の分類であるため注意。
参考サイト
- (参考サイトはありません)
// Sample.java
public class Sample
{
public static void main( String[] args )
{
// 「ラベル名:ステートメント」が「ラベルステートメント」
// となります。たとえば「ブロック」ステートメントを使用する
// 場合には以下のようになります。
label_name:{}
// breakでラベル名を指定することで、ラベル名の後の
// ブロックのすぐ外へと移動することができます。
label_out:
{
System.out.println( "外側ループ開始" );
for( int iF1 = 0; iF1 < 2; ++iF1 )
{
System.out.println( "内側ループ開始" );
for( int iF2 = 0; iF2 < 100; ++iF2 )
{
System.out.println( iF1 + ", " + iF2 );
if (
( iF1 == 0 ) &&
( iF2 == 2 )
)
{
// 普通のbreak。
break;
}
if (
( iF1 == 1 ) &&
( iF2 == 2 )
)
{
// ラベルを指定したbreak。
break label_out;
}
}
}
}
System.out.println( "label_outのブロックの外。" );
// 外側ループ開始
// 内側ループ開始
// 0, 0
// 0, 1
// 0, 2
// 内側ループ開始
// 1, 0
// 1, 1
// 1, 2
// label_outのブロックの外。
// このように、「break ラベル名;」という形で
// 「ラベル名:{}」のすぐ後に移動します。
// 「ラベル名:」の後ろにはステートメントであれば
// なんでも記述できます。そのため、以下のように
// forの前に記述することもできます。
System.out.println( "外側ループ開始" );
label_for: for( int iF1 = 0; iF1 < 2; ++iF1 )
{
System.out.println( "内側ループ開始" );
for( int iF2 = 0; iF2 < 100; ++iF2 )
{
System.out.println( iF1 + ", " + iF2 );
if (
( iF1 == 0 ) &&
( iF2 == 2 )
)
{
// ラベルを指定したbreak。
break label_for;
}
}
}
System.out.println( "外側のforループの外。" );
// 外側ループ開始
// 内側ループ開始
// 0, 0
// 0, 1
// 0, 2
// 外側のforループの外。
// 「break ラベル名;」の指定をする場合、forやwhileとは
// 関係なく移動できます。
for( int iF1 = 0; iF1 < 3; ++iF1 )
{
System.out.println( iF1 );
System.out.println( "label_inの前" );
label_in:
{
System.out.println( "label_inの最初" );
if( iF1 == 1 )
{
// iF1が1の時だけbreakします。
break label_in;
}
System.out.println( "label_inの最後" );
}
System.out.println( "label_inの後" );
}
// 0
// label_inの前
// label_inの最初
// label_inの最後
// label_inの後
// 1
// label_inの前
// label_inの最初
// label_inの後
// 2
// label_inの前
// label_inの最初
// label_inの最後
// label_inの後
// iF1が1の時だけ「label_inの最後」がありません。
// label_inで指定したラベルの後のブロックの直後に
// 移動しているからです。
// forやwhileの中じゃなくてもbreak可能です。
System.out.println( "label_normalblockの前" );
label_normalblock:
{
System.out.println( "label_normalblockの最初" );
break label_normalblock;
// System.out.println( "label_normalblockの最後" );
// コンパイルエラー:
// 到達不能コード
}
System.out.println( "label_normalblockの後" );
// label_normalblockの前
// label_normalblockの最初
// label_normalblockの後
// ネストが異なれば同じ名前のラベルがあっても問題ありません。
label_AAA:{}
label_AAA:{}
// ネスト外のラベルにbreakすることはできません。
label_other:{}
// break label_other;
// コンパイルエラー:
// 欠落ラベル label_other
// 同じ名前のラベルがネスト内に2つ以上あるとコンパイルエラーです。
label_samename:
{
// label_samename:{}
// コンパイルエラー:
// 重複ラベル label_samename
}
// ラベルの後には、ブロックに限らずステートメントを
// 記述することができます。
// ですので、以下のように代入や式、空ステートメントも記述できます。
// ただ、当然そのステートメントの中でbreakやcontinueが
// 使用できないと意味がありません。
int i;
label_assignment: i = 100;
label_expression: i = i + 200;
label_empty:;
// continueでラベル名を指定することで、指定したforループや
// whileループの「次の周」へと移ることができます。
label_out:
{
System.out.println( "外側ループ開始" );
label_for: for( int iF1 = 0; iF1 < 3; ++iF1 )
{
label_mid:
{
System.out.println( "内側ループ開始" );
for( int iF2 = 0; iF2 < 4; ++iF2 )
{
label_in:
{
System.out.println( iF1 + ", " + iF2 );
if (
( iF1 == 0 ) &&
( iF2 == 2 )
)
{
// 普通のcontinue。
continue;
}
if (
( iF1 == 1 ) &&
( iF2 == 2 )
)
{
// ラベルを指定したcontinue。外側のforの
// iF2が2の周がスタートします。
continue label_for;
}
// forやwhileといった、ループと関係のあるステートメント
// の前にないラベルは指定できません。
// continue label_out;
// コンパイルエラー:
// ループ継続ポイントがありません。
// continue label_mid;
// コンパイルエラー:
// ループ継続ポイントがありません。
// continue label_in;
// コンパイルエラー:
// ループ継続ポイントがありません。
}
}
}
}
}
// 外側ループ開始
// 内側ループ開始
// 0, 0
// 0, 1
// 0, 2
// 0, 3
// 内側ループ開始
// 1, 0
// 1, 1
// 1, 2
// 内側ループ開始
// 2, 0
// 2, 1
// 2, 2
// 2, 3
// iF1が1の時の周でlabel_forにcontinueで飛んでいます。
// 中のforから見るとbreakみたいに見えます。
}
}
public class Sample
{
public static void main( String[] args )
{
// 「ラベル名:ステートメント」が「ラベルステートメント」
// となります。たとえば「ブロック」ステートメントを使用する
// 場合には以下のようになります。
label_name:{}
// breakでラベル名を指定することで、ラベル名の後の
// ブロックのすぐ外へと移動することができます。
label_out:
{
System.out.println( "外側ループ開始" );
for( int iF1 = 0; iF1 < 2; ++iF1 )
{
System.out.println( "内側ループ開始" );
for( int iF2 = 0; iF2 < 100; ++iF2 )
{
System.out.println( iF1 + ", " + iF2 );
if (
( iF1 == 0 ) &&
( iF2 == 2 )
)
{
// 普通のbreak。
break;
}
if (
( iF1 == 1 ) &&
( iF2 == 2 )
)
{
// ラベルを指定したbreak。
break label_out;
}
}
}
}
System.out.println( "label_outのブロックの外。" );
// 外側ループ開始
// 内側ループ開始
// 0, 0
// 0, 1
// 0, 2
// 内側ループ開始
// 1, 0
// 1, 1
// 1, 2
// label_outのブロックの外。
// このように、「break ラベル名;」という形で
// 「ラベル名:{}」のすぐ後に移動します。
// 「ラベル名:」の後ろにはステートメントであれば
// なんでも記述できます。そのため、以下のように
// forの前に記述することもできます。
System.out.println( "外側ループ開始" );
label_for: for( int iF1 = 0; iF1 < 2; ++iF1 )
{
System.out.println( "内側ループ開始" );
for( int iF2 = 0; iF2 < 100; ++iF2 )
{
System.out.println( iF1 + ", " + iF2 );
if (
( iF1 == 0 ) &&
( iF2 == 2 )
)
{
// ラベルを指定したbreak。
break label_for;
}
}
}
System.out.println( "外側のforループの外。" );
// 外側ループ開始
// 内側ループ開始
// 0, 0
// 0, 1
// 0, 2
// 外側のforループの外。
// 「break ラベル名;」の指定をする場合、forやwhileとは
// 関係なく移動できます。
for( int iF1 = 0; iF1 < 3; ++iF1 )
{
System.out.println( iF1 );
System.out.println( "label_inの前" );
label_in:
{
System.out.println( "label_inの最初" );
if( iF1 == 1 )
{
// iF1が1の時だけbreakします。
break label_in;
}
System.out.println( "label_inの最後" );
}
System.out.println( "label_inの後" );
}
// 0
// label_inの前
// label_inの最初
// label_inの最後
// label_inの後
// 1
// label_inの前
// label_inの最初
// label_inの後
// 2
// label_inの前
// label_inの最初
// label_inの最後
// label_inの後
// iF1が1の時だけ「label_inの最後」がありません。
// label_inで指定したラベルの後のブロックの直後に
// 移動しているからです。
// forやwhileの中じゃなくてもbreak可能です。
System.out.println( "label_normalblockの前" );
label_normalblock:
{
System.out.println( "label_normalblockの最初" );
break label_normalblock;
// System.out.println( "label_normalblockの最後" );
// コンパイルエラー:
// 到達不能コード
}
System.out.println( "label_normalblockの後" );
// label_normalblockの前
// label_normalblockの最初
// label_normalblockの後
// ネストが異なれば同じ名前のラベルがあっても問題ありません。
label_AAA:{}
label_AAA:{}
// ネスト外のラベルにbreakすることはできません。
label_other:{}
// break label_other;
// コンパイルエラー:
// 欠落ラベル label_other
// 同じ名前のラベルがネスト内に2つ以上あるとコンパイルエラーです。
label_samename:
{
// label_samename:{}
// コンパイルエラー:
// 重複ラベル label_samename
}
// ラベルの後には、ブロックに限らずステートメントを
// 記述することができます。
// ですので、以下のように代入や式、空ステートメントも記述できます。
// ただ、当然そのステートメントの中でbreakやcontinueが
// 使用できないと意味がありません。
int i;
label_assignment: i = 100;
label_expression: i = i + 200;
label_empty:;
// continueでラベル名を指定することで、指定したforループや
// whileループの「次の周」へと移ることができます。
label_out:
{
System.out.println( "外側ループ開始" );
label_for: for( int iF1 = 0; iF1 < 3; ++iF1 )
{
label_mid:
{
System.out.println( "内側ループ開始" );
for( int iF2 = 0; iF2 < 4; ++iF2 )
{
label_in:
{
System.out.println( iF1 + ", " + iF2 );
if (
( iF1 == 0 ) &&
( iF2 == 2 )
)
{
// 普通のcontinue。
continue;
}
if (
( iF1 == 1 ) &&
( iF2 == 2 )
)
{
// ラベルを指定したcontinue。外側のforの
// iF2が2の周がスタートします。
continue label_for;
}
// forやwhileといった、ループと関係のあるステートメント
// の前にないラベルは指定できません。
// continue label_out;
// コンパイルエラー:
// ループ継続ポイントがありません。
// continue label_mid;
// コンパイルエラー:
// ループ継続ポイントがありません。
// continue label_in;
// コンパイルエラー:
// ループ継続ポイントがありません。
}
}
}
}
}
// 外側ループ開始
// 内側ループ開始
// 0, 0
// 0, 1
// 0, 2
// 0, 3
// 内側ループ開始
// 1, 0
// 1, 1
// 1, 2
// 内側ループ開始
// 2, 0
// 2, 1
// 2, 2
// 2, 3
// iF1が1の時の周でlabel_forにcontinueで飛んでいます。
// 中のforから見るとbreakみたいに見えます。
}
}
// Sample.java public class Sample { public static void main( String[] args ) { // 「ラベル名:ステートメント」が「ラベルステートメント」 // となります。たとえば「ブロック」ステートメントを使用する // 場合には以下のようになります。 label_name:{} // breakでラベル名を指定することで、ラベル名の後の // ブロックのすぐ外へと移動することができます。 label_out: { System.out.println( "外側ループ開始" ); for( int iF1 = 0; iF1 < 2; ++iF1 ) { System.out.println( "内側ループ開始" ); for( int iF2 = 0; iF2 < 100; ++iF2 ) { System.out.println( iF1 + ", " + iF2 ); if ( ( iF1 == 0 ) && ( iF2 == 2 ) ) { // 普通のbreak。 break; } if ( ( iF1 == 1 ) && ( iF2 == 2 ) ) { // ラベルを指定したbreak。 break label_out; } } } } System.out.println( "label_outのブロックの外。" ); // 外側ループ開始 // 内側ループ開始 // 0, 0 // 0, 1 // 0, 2 // 内側ループ開始 // 1, 0 // 1, 1 // 1, 2 // label_outのブロックの外。 // このように、「break ラベル名;」という形で // 「ラベル名:{}」のすぐ後に移動します。 // 「ラベル名:」の後ろにはステートメントであれば // なんでも記述できます。そのため、以下のように // forの前に記述することもできます。 System.out.println( "外側ループ開始" ); label_for: for( int iF1 = 0; iF1 < 2; ++iF1 ) { System.out.println( "内側ループ開始" ); for( int iF2 = 0; iF2 < 100; ++iF2 ) { System.out.println( iF1 + ", " + iF2 ); if ( ( iF1 == 0 ) && ( iF2 == 2 ) ) { // ラベルを指定したbreak。 break label_for; } } } System.out.println( "外側のforループの外。" ); // 外側ループ開始 // 内側ループ開始 // 0, 0 // 0, 1 // 0, 2 // 外側のforループの外。 // 「break ラベル名;」の指定をする場合、forやwhileとは // 関係なく移動できます。 for( int iF1 = 0; iF1 < 3; ++iF1 ) { System.out.println( iF1 ); System.out.println( "label_inの前" ); label_in: { System.out.println( "label_inの最初" ); if( iF1 == 1 ) { // iF1が1の時だけbreakします。 break label_in; } System.out.println( "label_inの最後" ); } System.out.println( "label_inの後" ); } // 0 // label_inの前 // label_inの最初 // label_inの最後 // label_inの後 // 1 // label_inの前 // label_inの最初 // label_inの後 // 2 // label_inの前 // label_inの最初 // label_inの最後 // label_inの後 // iF1が1の時だけ「label_inの最後」がありません。 // label_inで指定したラベルの後のブロックの直後に // 移動しているからです。 // forやwhileの中じゃなくてもbreak可能です。 System.out.println( "label_normalblockの前" ); label_normalblock: { System.out.println( "label_normalblockの最初" ); break label_normalblock; // System.out.println( "label_normalblockの最後" ); // コンパイルエラー: // 到達不能コード } System.out.println( "label_normalblockの後" ); // label_normalblockの前 // label_normalblockの最初 // label_normalblockの後 // ネストが異なれば同じ名前のラベルがあっても問題ありません。 label_AAA:{} label_AAA:{} // ネスト外のラベルにbreakすることはできません。 label_other:{} // break label_other; // コンパイルエラー: // 欠落ラベル label_other // 同じ名前のラベルがネスト内に2つ以上あるとコンパイルエラーです。 label_samename: { // label_samename:{} // コンパイルエラー: // 重複ラベル label_samename } // ラベルの後には、ブロックに限らずステートメントを // 記述することができます。 // ですので、以下のように代入や式、空ステートメントも記述できます。 // ただ、当然そのステートメントの中でbreakやcontinueが // 使用できないと意味がありません。 int i; label_assignment: i = 100; label_expression: i = i + 200; label_empty:; // continueでラベル名を指定することで、指定したforループや // whileループの「次の周」へと移ることができます。 label_out: { System.out.println( "外側ループ開始" ); label_for: for( int iF1 = 0; iF1 < 3; ++iF1 ) { label_mid: { System.out.println( "内側ループ開始" ); for( int iF2 = 0; iF2 < 4; ++iF2 ) { label_in: { System.out.println( iF1 + ", " + iF2 ); if ( ( iF1 == 0 ) && ( iF2 == 2 ) ) { // 普通のcontinue。 continue; } if ( ( iF1 == 1 ) && ( iF2 == 2 ) ) { // ラベルを指定したcontinue。外側のforの // iF2が2の周がスタートします。 continue label_for; } // forやwhileといった、ループと関係のあるステートメント // の前にないラベルは指定できません。 // continue label_out; // コンパイルエラー: // ループ継続ポイントがありません。 // continue label_mid; // コンパイルエラー: // ループ継続ポイントがありません。 // continue label_in; // コンパイルエラー: // ループ継続ポイントがありません。 } } } } } // 外側ループ開始 // 内側ループ開始 // 0, 0 // 0, 1 // 0, 2 // 0, 3 // 内側ループ開始 // 1, 0 // 1, 1 // 1, 2 // 内側ループ開始 // 2, 0 // 2, 1 // 2, 2 // 2, 3 // iF1が1の時の周でlabel_forにcontinueで飛んでいます。 // 中のforから見るとbreakみたいに見えます。 } }