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機能は必要ありません。
Javaのgoto
コンセプトに直接相当するものはありません。古典的なgoto
でできることのいくつかをいくつかのできるコンストラクトがあります。
break
およびcontinue
ステートメントを使用すると、ループまたはスイッチステートメントでブロックから飛び出すことができます。break <label>
を使用すると、任意の複合ステートメントから特定のメソッド(または初期化ブロック)内の任意のレベルにジャンプできます。continue <label>
を使用して、内側のループから外側のループの次の反復を続行できます。return
があります。これらのJava構造体のいずれも、現在のステートメントと同じレベルの入れ子にあるコード内のポイントまたは後方への分岐を許可しません。それらはすべて、1つ以上のネスト(スコープ)レベルを飛び出し、すべて(continue
を除く)下方にジャンプします。この制限は、古いBASIC、FORTRAN、およびCOBOLコードに固有のgoto「スパゲッティコード」症候群を回避するのに役立ちます2。
1-例外の最も高価な部分は、例外オブジェクトとそのスタックトレースの実際の作成です。 「通常の」フロー制御に本当に本当に例外処理を使用する必要がある場合は、例外オブジェクトを事前に割り当て/再利用するか、fillInStackTrace()
メソッドをオーバーライドするカスタム例外クラスを作成できます。欠点は、例外のprintStackTrace()
メソッドでは有用な情報が得られないことです...呼び出す必要がある場合です。
2-スパゲッティコードシンドロームは、利用可能な言語構成要素の使用を制限する 構造化プログラミング アプローチを生み出しました。これは BASIC 、 Fortran および COBOL に適用できますが、注意と訓練が必要です。 goto
を完全に削除することは、実用的に優れたソリューションでした。あなたが言語でそれを保持する場合、それを乱用するピエロが常に存在します。
楽しみのために、 here は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を表現していることを示唆しています。セマンティクス。
具体的には、2番目の例のdo {...} while(true);
ループは、ループ条件を評価しないように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つ...
マット・ウルフはこう書いている:
人々はいつも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
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++) {"