85

Javaのgotoキーワードの代替関数は何ですか?

Javaにはgotoがないので。

4

11 に答える 11

84

ラベル付きのBREAKステートメントを使用できます。

search:
    for (i = 0; i < arrayOfInts.length; i++) {
        for (j = 0; j < arrayOfInts[i].length; j++) {
            if (arrayOfInts[i][j] == searchfor) {
                foundIt = true;
                break search;
            }
        }
    }

ただし、適切に設計されたコードでは、GOTO機能は必要ありません。

于 2010-03-12T05:54:46.900 に答える
42

gotoJavaの概念に直接相当するものはありません。クラシックでできることのいくつかを実行できるようにするいくつかの構成がありますgoto

  • breakandステートメントを使用するcontinueと、ループまたはswitchステートメントのブロックからジャンプできます。
  • ラベル付きステートメントbreak <label>。任意の複合ステートメントから、特定のメソッド(または初期化ブロック)内の任意のレベルにジャンプできます。
  • ループステートメントにラベルを付けるcontinue <label>と、内側のループから外側のループの次の反復を続行できます。
  • 例外をスローしてキャッチすると、メソッド呼び出しの多くのレベルから(効果的に)ジャンプできます。(ただし、例外は比較的高価であり、「通常の」制御フロー1を実行するための悪い方法と見なされます。)
  • そしてもちろん、ありますreturn

これらのJava構造はいずれも、現在のステートメントと同じレベルのネストで、コード内のあるポイントに逆方向に分岐することはできません。それらはすべて、1つ以上のネスト(スコープ)レベルから飛び出し、(を除いてcontinue)すべて下にジャンプします。この制限は、古いBASIC、FORTRAN、およびCOBOLコード2に固有のgoto「スパゲッティコード」シンドロームを回避するのに役立ちます。


1-例外の最もコストのかかる部分は、例外オブジェクトとそのスタックトレースの実際の作成です。本当に「通常の」フロー制御に例外処理を使用する必要がある場合は、例外オブジェクトを事前に割り当て/再利用するか、fillInStackTrace()メソッドをオーバーライドするカスタム例外クラスを作成できます。欠点は、例外のprintStackTrace()メソッドが有用な情報を提供しないことです...万が一それらを呼び出す必要がある場合。

2-スパゲッティコードシンドロームは、利用可能な言語構造の使用を制限する構造化プログラミングアプローチを生み出しました。これは、 BASICFortran、およびCOBOLに適用できますが、注意と規律が必要でした。完全に取り除くgotoことは、実用的に優れた解決策でした。あなたがそれを言語で保つならば、それを乱用する何人かの道化師が常にいます。

于 2010-03-12T06:03:07.057 に答える
31

楽しみのために、これJavaでのGOTO実装です。

例:

   1 public class GotoDemo {
   2     public static void main(String[] args) {
   3         int i = 3;
   4         System.out.println(i);
   5         i = i - 1;
   6         if (i >= 0) {
   7             GotoFactory.getSharedInstance().getGoto().go(4);
   8         }
   9         
  10         try {
  11             System.out.print("Hell");
  12             if (Math.random() > 0) throw new Exception();            
  13             System.out.println("World!");
  14         } catch (Exception e) {
  15             System.out.print("o ");
  16             GotoFactory.getSharedInstance().getGoto().go(13);
  17         }
  18     }
  19 }

それを実行する:

$ java -cp bin:asm-3.1.jar GotoClassLoader GotoDemo           
   3
   2
   1
   0
   Hello World!

「使わないで!」を追加する必要がありますか?

于 2010-03-12T06:50:17.723 に答える
18

一部のコメント提供者や反対派は、これはgotoではないと主張していますが、以下のJavaステートメントから生成されたバイトコードは、これらのステートメントが実際にgotoセマンティクスを表現していることを示しています。

具体的にはdo {...} while(true);、2番目の例のループは、ループ状態を評価しないようにJavaコンパイラーによって最適化されています。

前にジャンプ

label: {
  // do stuff
  if (check) break label;
  // do more stuff
}

バイトコード:

2  iload_1 [check]
3  ifeq 6          // Jumping forward
6  ..

後ろにジャンプする

label: do {
  // do stuff
  if (check) continue label;
  // do more stuff
  break label;
} while(true);

バイトコード:

 2  iload_1 [check]
 3  ifeq 9
 6  goto 2          // Jumping backward
 9  ..
于 2011-06-16T14:08:51.083 に答える
5

gotoステートメントのようなものが本当に必要な場合は、いつでも名前付きブロックに分割してみることができます。

ラベルを破るには、ブロックの範囲内にいる必要があります。

namedBlock: {
  if (j==2) {
    // this will take you to the label above
    break namedBlock;
  }
}

gotoを避けるべき理由については説明しません。その答えはすでにご存知だと思います。

于 2010-03-12T05:58:10.450 に答える
4
public class TestLabel {

    enum Label{LABEL1, LABEL2, LABEL3, LABEL4}

    /**
     * @param args
     */
    public static void main(String[] args) {

        Label label = Label.LABEL1;

        while(true) {
            switch(label){
                case LABEL1:
                    print(label);

                case LABEL2:
                    print(label);
                    label = Label.LABEL4;
                    continue;

                case LABEL3:
                    print(label);
                    label = Label.LABEL1;
                    break;

                case LABEL4:
                    print(label);
                    label = Label.LABEL3;
                    continue;
            }
            break;
        }
    }

    public final static void print(Label label){
        System.out.println(label);
    }
于 2011-03-04T08:30:26.597 に答える
3

StephenCは次のように書いています。

従来のgotoで実行できることのいくつかを実行できるようにする2つの構成があります。

もう1つ...

MattWolfeは次のように書いています。

人々はいつもgotoを使わないことについて話しますが、かなりよく知られていて使われている本当に良い実世界のユースケースがあると思います。つまり、関数から戻る前に必ずコードを実行してください。ロックかどうかはわかりませんが、私の場合は、必要なクリーンアップを実行できるように、戻る直前に休憩にジャンプできるようにしたいと思います。

try {
    // do stuff
    return result;  // or break, etc.
}
finally {
    // clean up before actually returning, even though the order looks wrong.
}

http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html

finallyブロックは、tryブロックが終了するときに常に実行されます。これにより、予期しない例外が発生した場合でも、finallyブロックが確実に実行されます。しかし、finallyは、単なる例外処理以上の用途に役立ちます。これにより、プログラマーは、リターン、続行、または中断によってクリーンアップコードが誤ってバイパスされるのを防ぐことができます。例外が予想されない場合でも、finallyブロックにクリーンアップコードを配置することは常に良い習慣です。

finallyに関連するばかげたインタビューの質問は次のとおりです。try{}ブロックから戻ったが、finally {}にも戻りがある場合、どの値が返されますか?

于 2013-02-07T14:36:33.537 に答える
1

最も簡単な方法は次のとおりです。

int label = 0;
loop:while(true) {
    switch(state) {
        case 0:
            // Some code
            state = 5;
            break;

        case 2:
            // Some code
            state = 4;
            break;
        ...
        default:
            break loop;
    }
}
于 2014-03-17T10:58:56.620 に答える
0

以下のコードを試してください。わたしにはできる。

for (int iTaksa = 1; iTaksa <=8; iTaksa++) { // 'Count 8 Loop is  8 Taksa

    strTaksaStringStar[iCountTaksa] = strTaksaStringCount[iTaksa];

    LabelEndTaksa_Exit : {
        if (iCountTaksa == 1) { //If count is 6 then next it's 2
            iCountTaksa = 2;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 2) { //If count is 2 then next it's 3
            iCountTaksa = 3;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 3) { //If count is 3 then next it's 4
            iCountTaksa = 4;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 4) { //If count is 4 then next it's 7
            iCountTaksa = 7;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 7) { //If count is 7 then next it's 5
            iCountTaksa = 5;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 5) { //If count is 5 then next it's 8
            iCountTaksa = 8;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 8) { //If count is 8 then next it's 6
            iCountTaksa = 6;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 6) { //If count is 6 then loop 1  as 1 2 3 4 7 5 8 6  --> 1
            iCountTaksa = 1;
            break  LabelEndTaksa_Exit;
        }
    }   //LabelEndTaksa_Exit : {

} // "for (int iTaksa = 1; iTaksa <=8; iTaksa++) {"
于 2013-03-16T14:53:46.010 に答える
-1

gotoの代わりに、ラベル付きのブレークを使用します。

于 2014-11-25T09:12:50.887 に答える
-1

Javagotoには、コードが構造化されておらず、読みにくくなるため、がありません。ただし、gotoの文明化breakされた形式continueとして問題なく使用できます。


ブレークを使用して前にジャンプ-

ahead: {
    System.out.println("Before break");
    break ahead;
    System.out.println("After Break"); // This won't execute
}
// After a line break ahead, the code flow starts from here, after the ahead block
System.out.println("After ahead");

出力

Before Break
After ahead

続行を使用して後方にジャンプする

before: {
    System.out.println("Continue");
    continue before;
}

これにより、行が実行されるたびにコードフローがから再開されるため、無限ループが発生します。continue beforebefore

于 2014-12-08T07:23:36.027 に答える