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)이 아닙니다.
break
for 문을 종료 하는 도달 가능한 문이 있습니다.
따라서 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에 의해 제공됩니다.
'Development Tip' 카테고리의 다른 글
pytz 요구 사항을 충족하는 버전을 찾을 수 없습니다. (0) | 2020.12.12 |
---|---|
편집기 창 분할 바로 가기는 무엇입니까? (0) | 2020.12.12 |
undefined 값을 설정하면 어떻게됩니까? (0) | 2020.12.12 |
동적 할당없이 런타임에 배열 크기가 허용됩니까? (0) | 2020.12.12 |
WPF 컨트롤에 대한 Binding.Mode = Default의 기본값은 무엇입니까? (0) | 2020.12.12 |