89

2001 年の古いコードを調べていると、次のステートメントに出くわしました。

   else {
     do {
       int c = XMLDocumentFragmentScannerImpl.this.scanContent();
       if (c == 60) {
         XMLDocumentFragmentScannerImpl.this.fEntityScanner.scanChar();
         XMLDocumentFragmentScannerImpl.this.setScannerState(1);
         break label913;
       }

私はこれまで見たことがありませんでしたが、ここでラベル付きのブレークを発見しました:

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html

これは本質的に次のように機能しませんgotoか?それを使用することは良い習慣ですか?それは私を不安にさせます。

4

6 に答える 6

129

いいえ、制御フローの別の部分に「移動」できないため、goto とは異なります。

リンクしたページから:

break ステートメントは、ラベル付きステートメントを終了します。制御の流れをラベルに転送しません。制御フローは、ラベル付けされた (終了した) ステートメントの直後のステートメントに転送されます。

これは、現在実行中のループのみを中断できることを意味します。

次の例を検討してください。

first:
for( int i = 0; i < 10; i++) {
  second:
  for(int j = 0; j < 5; j ++ )
  {
    break xxx;
  }
}

third:
for( int a = 0; a < 10; a++) {

}

ステートメントをヒットしたときに両方のループが実行されているため、(外側または内側のループを中断するために) xxxorfirstに置き換えることができますが、に置き換えるとコンパイルされません。secondbreakxxxthird

于 2013-02-19T14:56:45.340 に答える
16

gotoラベル付けされたステートメント(通常はループ構造)の最後にのみ制御を送信するため、それほどひどいものではありません。あり得ないことgotoは、メソッドソースの上位にあるラベルを含め、どこへでも任意に分岐するため、自家製のループ動作を実行できることです。Javaのラベル解除機能では、制御が進むだけなので、そのような狂気は許されません。

私は約12年前に一度だけ使用しましたが、ネストされたループから抜け出す必要がある状況では、より構造化された代替手段により、ループでのより複雑なテストが可能になります。あまり使用することはお勧めしませんが、自動の悪臭としてフラグを立てることはしません。

于 2013-02-19T14:59:02.703 に答える
8

この回答の残りの部分を読む前に、有害と見なされるステートメントに移動 をお読みください。全部を読みたくない場合は、ここに私が重要なポイントと考えるものを示します。

go to ステートメントを自由に使用すると、プロセスの進行状況を説明するための意味のある座標セットを見つけるのが非常に難しくなるという直接的な結果が生じます。

言い換えれば、問題gotoは、プログラマーがその時点でのプログラムの状態を理解することなく、プログラムがコードブロックの途中で到着する可能性があることです。標準のブロック指向の構造は、状態遷移を明確に描写するように設計されています。ラベル付きbreakは、プログラムを特定の既知の状態 (ラベル付きブロックを含む) に移行させることを目的としています。

実際の命令型プログラムでは、状態はブロック境界によって明確に区切られていないため、ラベル付けbreakが適切かどうかは疑問です。ブロックの外部から見えるブロックの状態変化があり、ブロックを出るポイントが複数ある場合、 ラベル付きbreakは プリミティブ と同等gotoです。唯一の違いは、不確定状態のブロックの途中に着地する可能性ではなく、不確定状態の新しいブロックを開始することです。

したがって、一般的に、ラベル付けbreakされたものは危険であると考えます。私の意見では、これはブロックを関数に変換する必要があるというサインであり、囲んでいるスコープへのアクセスは制限されています。

ただし、このサンプル コードは明らかにパーサー ジェネレーターの製品です (OP は Xerces ソース コードであるとコメントしています)。また、パーサー ジェネレーター (または一般的なコード ジェネレーター) は、状態について完全な知識を持っており、人間がそれを理解する必要がないため、生成するコードを自由に使用することがよくあります。

于 2013-02-19T16:19:57.380 に答える
1

これはgoto、フロー制御を逆方向にジャンプするステートメントとは異なります。ラベルは、中断が発生した場所を(プログラマーに)示すだけです。また、フロー制御は。の後の次のステートメントに転送されbreakます。

個人的には、数千行に相当するコードを書き始めると意味がなくなるので、あまり役に立たないと思います。しかし、繰り返しになりますが、それはユースケースによって異なります。

于 2013-02-19T14:59:02.607 に答える