Javaのgotoキーワードの代替関数は何ですか?
Javaにはgotoがないので。
ラベル付きの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機能は必要ありません。
goto
Javaの概念に直接相当するものはありません。クラシックでできることのいくつかを実行できるようにするいくつかの構成がありますgoto
。
break
andステートメントを使用するcontinue
と、ループまたはswitchステートメントのブロックからジャンプできます。break <label>
。任意の複合ステートメントから、特定のメソッド(または初期化ブロック)内の任意のレベルにジャンプできます。continue <label>
と、内側のループから外側のループの次の反復を続行できます。return
。これらのJava構造はいずれも、現在のステートメントと同じレベルのネストで、コード内のあるポイントに逆方向に分岐することはできません。それらはすべて、1つ以上のネスト(スコープ)レベルから飛び出し、(を除いてcontinue
)すべて下にジャンプします。この制限は、古いBASIC、FORTRAN、およびCOBOLコード2に固有のgoto「スパゲッティコード」シンドロームを回避するのに役立ちます。
1-例外の最もコストのかかる部分は、例外オブジェクトとそのスタックトレースの実際の作成です。本当に「通常の」フロー制御に例外処理を使用する必要がある場合は、例外オブジェクトを事前に割り当て/再利用するか、fillInStackTrace()
メソッドをオーバーライドするカスタム例外クラスを作成できます。欠点は、例外のprintStackTrace()
メソッドが有用な情報を提供しないことです...万が一それらを呼び出す必要がある場合。
2-スパゲッティコードシンドロームは、利用可能な言語構造の使用を制限する構造化プログラミングアプローチを生み出しました。これは、 BASIC、Fortran、およびCOBOLに適用できますが、注意と規律が必要でした。完全に取り除くgoto
ことは、実用的に優れた解決策でした。あなたがそれを言語で保つならば、それを乱用する何人かの道化師が常にいます。
楽しみのために、これが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!
「使わないで!」を追加する必要がありますか?
一部のコメント提供者や反対派は、これは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 ..
gotoステートメントのようなものが本当に必要な場合は、いつでも名前付きブロックに分割してみることができます。
ラベルを破るには、ブロックの範囲内にいる必要があります。
namedBlock: {
if (j==2) {
// this will take you to the label above
break namedBlock;
}
}
gotoを避けるべき理由については説明しません。その答えはすでにご存知だと思います。
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);
}
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 {}にも戻りがある場合、どの値が返されますか?
最も簡単な方法は次のとおりです。
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;
}
}
以下のコードを試してください。わたしにはできる。
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++) {"
gotoの代わりに、ラベル付きのブレークを使用します。
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 before
before