Development Tip

Java 컴파일러가 연결할 수없는 then 문에 대해 연결할 수없는 문 오류를 생성하지 않는 이유는 무엇입니까?

yourdevel 2020. 12. 12. 12:31
반응형

Java 컴파일러가 연결할 수없는 then 문에 대해 연결할 수없는 문 오류를 생성하지 않는 이유는 무엇입니까?


컴파일을 시도하면

for(;;)
{

}
System.out.println("End");

Java 컴파일러에서 Unreachable statement. 그러나 내가 또 다른 " 도달 할 수없는 "(나에 따르면) break진술을 추가하고 그것을 만들면 :

for(;;)
{
    if(false) break;
}
System.out.println("End");

컴파일됩니다. 왜 오류가 발생하지 않습니까?


동작은 연결할 수없는 문대한 JLS 설명에 정의되어 있습니다 .

if-then 문에 도달 할 수있는 경우 then- 문에 도달 할 수 있습니다.

따라서 컴파일러 break;는의 조건에 관계없이 then-statement ( )에 도달 할 수 있는지 확인 합니다 if.

그리고 조금 더 강조합니다.

for다음 중 하나 이상이 참인 경우 기본 명령문은 정상적으로 완료 될 수 있습니다.

  • for 문에 연결할 수 있고 조건식이 있으며 조건식이 값이 true 인 상수 식 (§15.28)이 아닙니다.
  • breakfor 문을 종료 하는 도달 가능한 문이 있습니다.

따라서 for는 then-statement에 break. 당신이 눈치대로 교체하는 경우, 그것은 작동하지 않을 것입니다 break함께 return.


이유는 섹션 끝 부분에 설명되어 있습니다. 실질적 if으로 다음과 같은 구조를 허용하는 특수 처리가 있습니다.

if(DEBUG) { ... }

여기서 DEBUG는 컴파일 시간 상수 일 수 있습니다.


비슷한 질문에 대한 내 답변 에서 설명했듯이 특정 구조 if(compile-time-false)는 명시 적 백도어로서 도달 불가능 규칙에서 제외됩니다. 이 경우 컴파일러는 break그 때문에 도달 가능한 것으로 간주합니다.


에서 JLS

다음 중 하나 이상이 참이면 if-then 문이 정상적으로 완료 될 수 있습니다.

> if-then 문에 도달 할 수 있고 조건식이 값이 true 인 상수식이 아닙니다.

> then-statement는 정상적으로 완료 될 수 있습니다.

그래서 if(false)허용됩니다.

이 "조건부 컴파일"기능은 이진 호환성에 상당한 영향을 미치며 이와 관계가 있습니다. 이러한 "플래그"변수를 사용하는 클래스 집합이 컴파일되고 조건부 코드가 생략되면 나중에 플래그 정의를 포함하는 클래스 또는 인터페이스의 새 버전 만 배포하는 것으로 충분하지 않습니다. 따라서 플래그 값의 변경은 기존 바이너리와 바이너리 호환되지 않습니다. (switch 문에서 case 레이블에 상수를 사용하는 것과 같은 비 호환성에 대한 다른 이유도 있습니다.)


기본적으로 도달 할 수없는 코드실제로 코드를 실행 하지 않고 프로그램을 정적으로 분석하여 감지됩니다 . 조건은 런타임에 확인 됩니다 . 따라서이 분석이 수행 될 때 실제로 조건을 조사하지 않고을 통해 액세스 할 수 있는지 ( 접근 가능한 ) 확인합니다 .break;if


Java가 도달 할 수없는 모든 명령문을 감지하지 못하는 핵심 이유 는 일반적으로 코드에 도달 할 수 있는지 여부에 대한 대답이 불가능하기 때문입니다. 이것은 튜링 머신에서 정지 문제 를 결정할 수 없다는 사실에서 비롯 됩니다.

따라서 도달 할 수없는 모든 명령문을 감지 할 수 없다는 것은 분명하지만 조건을 평가하지 않는 이유는 무엇입니까? 사용 된 조건이 단순한 false것이 아니라 ~x == x. 예를 들어, 이러한 모든 명령문은 true모든 int x( source )에 대해 인쇄 됩니다 .

    System.out.println((x + x & 1) == 0);
    System.out.println((x + -x & 1) == 0);
    System.out.println((-x & 1) == (x & 1));
    System.out.println(((-x ^ x) & 1) == 0);
    System.out.println((x * 0x80 & 0x56) == 0);
    System.out.println((x << 1 ^ 0x1765) != 0);

진술은 다소 복잡 할 수 있습니다. 해결하는 데 시간이 걸립니다. 빌드 시간이 크게 증가하고 결국 도달 할 수없는 모든 명령문을 감지하지 못합니다. 컴파일러는 약간의 노력을 기울이지 만 너무 많은 시간을 소비하지 않도록 설계되었습니다.

남은 유일한 질문은 조건 해결을 중단해야하는 곳입니다. 그 이유는 수학적 정당성이없는 것으로 보이며 사용 시나리오를 기반으로합니다. 특정 사례에 대한 근거는 JLS-14.21에 의해 제공됩니다.

참고URL : https://stackoverflow.com/questions/34453585/why-does-a-java-compiler-not-produce-an-unreachable-statement-error-for-an-unrea

반응형