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
및continue
문은 루프 또는 스위치 문에서 블록 밖으로 점프 할 수 있습니다.- 레이블이 지정된 문
break <label>
으로 임의의 복합 문에서 주어진 메서드 (또는 이니셜 라이저 블록) 내의 모든 수준으로 이동할 수 있습니다. - 루프 문에 레이블
continue <label>
을 지정하면 내부 루프에서 외부 루프의 다음 반복을 계속할 수 있습니다 . - 예외를 던지고 잡으면 여러 수준의 메서드 호출에서 (효과적으로) 점프 할 수 있습니다. (그러나 예외는 상대적으로 비용이 많이 들고 “일반적인”제어 흐름 1 을 수행하는 나쁜 방법으로 간주됩니다 .)
- 물론
return
.
이러한 Java 구성 중 어느 것도 현재 명령문과 동일한 중첩 수준에있는 코드의 한 지점 또는 역방향 분기를 허용하지 않습니다. 그들은 모두 하나 이상의 중첩 (범위) 레벨을 continue
뛰어 내리고 모두 (제외 ) 아래로 점프합니다. 이 제한은 이전 BASIC, FORTRAN 및 COBOL 코드 2에 내재 된 goto “스파게티 코드”증후군을 방지하는 데 도움이됩니다 .
1- 예외에서 가장 비용이 많이 드는 부분은 예외 개체와 스택 추적의 실제 생성입니다. 정말로 “정상”흐름 제어에 예외 처리를 사용해야하는 경우 예외 개체를 미리 할당 / 재사용하거나 fillInStackTrace()
메서드 를 재정의하는 사용자 지정 예외 클래스를 만들 수 있습니다 . 단점은 예외의 printStackTrace()
메서드가 유용한 정보를 제공하지 않는다는 것입니다.
2-스파게티 코드 신드롬은 사용 가능한 언어 구조의 사용을 제한 하는 구조적 프로그래밍 접근 방식을 생성했습니다. 이것은 BASIC , Fortran 및 COBOL에 적용될 수 있지만주의와 규율이 필요했습니다. goto
완전히 제거 하는 것이 실용적으로 더 나은 해결책이었습니다. 언어로 보관하면 항상 그것을 남용하는 광대가 있습니다.
답변
그냥 재미를 위해, 여기에 자바에서 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);
두 번째 예제의 루프는 루프 조건을 평가하지 않기 위해 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;
}
}
고토를 피해야하는 이유에 대해서는 설명하지 않겠습니다. 이미 그에 대한 답을 알고 있다고 가정합니다.
답변
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로 할 수있는 일을 할 수있는 두 가지 구조가 있습니다.
하나 더…
Matt Wolfe는 다음과 같이 씁니다.
사람들은 항상 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와 관련된 어리석은 인터뷰 질문은 다음과 같습니다. try {} 블록에서 돌아 왔지만 finally {}에도 반환이있는 경우 어떤 값이 반환됩니까?
