programing tip

Java에 "도달 할 수없는 문"컴파일러 오류가있는 이유는 무엇입니까?

itbloger 2020. 10. 10. 09:40
반응형

Java에 "도달 할 수없는 문"컴파일러 오류가있는 이유는 무엇입니까?


나는 종종 프로그램을 디버깅 할 때 코드 블록 안에 return 문을 삽입하는 것이 편리하다는 것을 알게됩니다. Java에서 이와 같은 것을 시도해 볼 수 있습니다 ....

class Test {
        public static void main(String args[]) {
                System.out.println("hello world");
                return;
                System.out.println("i think this line might cause a problem");
        }
}

물론 이것은 컴파일러 오류를 생성합니다.

Test.java:7 : 연결할 수없는 문

사용하지 않는 코드가 나쁜 습관으로 경고가 정당화되는 이유를 이해할 수 있습니다. 그러나 왜 이것이 오류를 생성 해야하는지 이해하지 못합니다.

이것은 단지 Java가 Nanny가 되려고하는 것입니까, 아니면 이것을 컴파일러 오류로 만드는 좋은 이유가 있습니까?


도달 할 수없는 코드는 컴파일러에게 의미가 없기 때문입니다. 사람들에게 의미있는 코드를 만드는 것은 컴파일러에게 의미있는 코드를 만드는 것보다 가장 중요하고 어렵지만 컴파일러는 코드의 필수 소비자입니다. 자바 설계자들은 컴파일러에게 의미가없는 코드는 오류라는 관점을 가지고 있습니다. 접근 할 수없는 코드가 있으면 수정해야 할 실수를 저질렀다는 입장입니다.

여기에 비슷한 질문이 있습니다. 연결할 수없는 코드 : 오류 또는 경고? , 저자는 "개인적으로는 이것이 오류라고 강하게 느낍니다. 프로그래머가 코드를 작성하는 경우 항상 일부 시나리오에서 실제로 실행하려는 의도가 있어야합니다."라고 말합니다. 분명히 Java의 언어 디자이너는 동의합니다.

도달 할 수없는 코드가 컴파일을 방해해야하는지 여부는 합의가 이루어지지 않는 문제입니다. 그러나 이것이 자바 디자이너가 한 이유입니다.


댓글의 많은 사람들은 Java가 컴파일을 방해하지 않는 도달 할 수없는 코드 클래스가 많다고 지적합니다. Gödel의 결과를 올바르게 이해하면 어떤 컴파일러도 도달 할 수없는 코드의 모든 클래스를 포착 할 수 없습니다.

단위 테스트는 모든 단일 버그를 포착 할 수 없습니다. 우리는 이것을 그들의 가치에 대한 논쟁으로 사용하지 않습니다. 마찬가지로 컴파일러는 문제가있는 모든 코드를 잡을 수는 없지만 가능한 경우 잘못된 코드의 컴파일을 방지하는 것이 여전히 중요합니다.

Java 언어 설계자는 연결할 수없는 코드를 오류로 간주합니다. 따라서 가능한 경우 컴파일을 방지하는 것이 합리적입니다.


(당신이 반대하기 전에 : 질문은 Java에 도달 할 수없는 명령문 컴파일러 오류가 있어야하는지 여부가 아닙니다. 문제는 Java에 도달 할 수없는 명령문 컴파일러 오류가있는 이유입니다. Java가 잘못된 설계 결정을 내렸다고 생각한다고해서 나를 반대하지 마십시오.)


도달 할 수없는 명령문이 허용되지 않아야하는 명확한 이유는 없습니다. 다른 언어는 문제없이 그들을 허용합니다. 특정 요구에 대해 다음은 일반적인 트릭입니다.

if (true) return;

무의미 ​​해 보이며, 코드를 읽는 사람은 나머지 문장을 접근 할 수없는 상태로 남겨 두는 부주의 한 실수가 아니라 의도적으로 수행 했어야한다고 추측 할 것입니다.

Java는 "조건부 컴파일"을 약간 지원합니다.

http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.21

if (false) { x=3; }

컴파일 타임 오류가 발생하지 않습니다. 최적화 컴파일러는 x = 3; 실행되지 않으며 생성 된 클래스 파일에서 해당 명령문에 대한 코드를 생략하도록 선택할 수 있지만 x = 3; 여기에 지정된 기술적 의미에서 "도달 할 수 없음"으로 간주되지 않습니다.

이 다른 처리의 근거는 프로그래머가 다음과 같은 "플래그 변수"를 정의 할 수 있도록하는 것입니다.

static final boolean DEBUG = false;

그런 다음 다음과 같은 코드를 작성하십시오.

if (DEBUG) { x=3; }

아이디어는 DEBUG의 값을 false에서 true로 또는 true에서 false로 변경 한 다음 프로그램 텍스트에 대한 다른 변경없이 코드를 올바르게 컴파일 할 수 있어야한다는 것입니다.


유모입니다. 나는 .Net이 이것을 맞았다 고 느낍니다. 도달 할 수없는 코드에 대한 경고를 일으키지 만 오류는 아닙니다. 경고를받는 것은 좋지만 컴파일을 막을 이유는 없습니다 (특히 코드를 우회하기 위해 리턴을 던지는 것이 좋은 디버깅 세션 동안).


나는 방금이 질문을 알아 차렸고 여기에 $ .02를 추가하고 싶었습니다.

Java의 경우 이것은 실제로 옵션이 아닙니다. "연결할 수없는 코드"오류는 JVM 개발자가 개발자를 모든 것으로부터 보호하거나 특별히 경계해야한다고 생각한 것이 아니라 JVM 사양의 요구 사항에서 비롯됩니다.

Java 컴파일러와 JVM은 모두 현재 메서드에 할당 된 스택의 모든 항목에 대한 명확한 정보 인 "스택 맵"을 사용합니다. JVM 명령어가 한 유형의 항목을 다른 유형으로 잘못 처리하지 않도록 스택의 모든 슬롯 유형을 알아야합니다. 이것은 숫자 값이 포인터로 사용되는 것을 방지하는 데 가장 중요합니다. Java 어셈블리를 사용하여 숫자를 푸시 / 저장 한 다음 개체 참조를 팝 /로드 할 수 있습니다. 그러나 JVM은 클래스 유효성 검사 중에이 코드를 거부합니다. 즉, 스택 맵을 만들고 일관성을 테스트 할 때입니다.

스택 맵을 확인하기 위해 VM은 메서드에있는 모든 코드 경로를 살펴보고 어떤 코드 경로가 실행 되든 관계없이 모든 명령어의 스택 데이터가 이전 코드가 푸시 한 것과 일치하는지 확인해야합니다. / 스택에 저장됩니다. 따라서 다음과 같은 간단한 경우 :

Object a;
if (something) { a = new Object(); } else { a = new String(); }
System.out.println(a);

3 행에서 JVM은 'if'의 두 분기가 Object와 호환되는 항목 (로컬 var # 0 일뿐)에만 저장되었는지 확인합니다 (3 행 이상의 코드가 로컬 var # 0을 처리하는 방법이기 때문에) ).

컴파일러가 도달 할 수없는 코드에 도달하면 해당 지점에서 스택이 어떤 상태인지 알지 못하므로 상태를 확인할 수 없습니다. 그 시점에서 더 이상 코드를 컴파일 할 수 없습니다. 지역 변수도 추적 할 수 없기 때문에 클래스 파일에이 모호함을 남기는 대신 치명적인 오류가 발생합니다.

Of course a simple condition like if (1<2) will fool it, but it's not really fooling - it's giving it a potential branch that can lead to the code, and at least both the compiler and the VM can determine, how the stack items can be used from there on.

P.S. I don't know what .NET does in this case, but I believe it will fail compilation as well. This normally will not be a problem for any machine code compilers (C, C++, Obj-C, etc.)


One of the goals of compilers is to rule out classes of errors. Some unreachable code is there by accident, it's nice that javac rules out that class of error at compile time.

For every rule that catches erroneous code, someone will want the compiler to accept it because they know what they're doing. That's the penalty of compiler checking, and getting the balance right is one of the tricker points of language design. Even with the strictest checking there's still an infinite number of programs that can be written, so things can't be that bad.


While I think this compiler error is a good thing, there is a way you can work around it. Use a condition you know will be true:

public void myMethod(){

    someCodeHere();

    if(1 < 2) return; // compiler isn't smart enough to complain about this

    moreCodeHere();

}

The compiler is not smart enough to complain about that.


It is certainly a good thing to complain the more stringent the compiler is the better, as far as it allows you to do what you need. Usually the small price to pay is to comment the code out, the gain is that when you compile your code works. A general example is Haskell about which people screams until they realize that their test/debugging is main test only and short one. I personally in Java do almost no debugging while being ( in fact on purpose) not attentive.


If the reason for allowing if (aBooleanVariable) return; someMoreCode; is to allow flags, then the fact that if (true) return; someMoreCode; does not generate a compile time error seems like inconsistency in the policy of generating CodeNotReachable exception, since the compiler 'knows' that true is not a flag (not a variable).

Two other ways which might be interesting, but don't apply to switching off part of a method's code as well as if (true) return:

Now, instead of saying if (true) return; you might want to say assert false and add -ea OR -ea package OR -ea className to the jvm arguments. The good point is that this allows for some granularity and requires adding an extra parameter to the jvm invocation so there is no need of setting a DEBUG flag in the code, but by added argument at runtime, which is useful when the target is not the developer machine and recompiling & transferring bytecode takes time.

There is also the System.exit(0) way, but this might be an overkill, if you put it in Java in a JSP then it will terminate the server.

Apart from that Java is by-design a 'nanny' language, I would rather use something native like C/C++ for more control.

참고URL : https://stackoverflow.com/questions/3795585/why-does-java-have-an-unreachable-statement-compiler-error

반응형