Java에서 도달 불가능한 문(Unreachable Statement)은 프로그램의 실행 흐름상 절대로 실행될 수 없는 코드를 의미합니다. 컴파일러는 조건의 값이 컴파일 시점에 확정되는 경우(final 상수 등) 해당 코드에 도달할 수 없다고 판단하여 컴파일 오류를 발생시킵니다.
반면 final이 아닌(non-final) 변수를 사용하면 이야기가 달라집니다. 변수의 값은 언제든 변경될 수 있으므로 컴파일러는 루프 뒤의 문장을 여전히 '도달 가능'하다고 간주합니다. 따라서 컴파일은 정상적으로 성공하지만, 실제 실행 시점에는 조건이 계속 참을 유지하여 루프가 무한히 반복되고 그 뒤의 문장은 영원히 실행되지 않습니다.
예제 코드
class Demo_example {
int a = 2, b = 3;
void display_msg(){
while (a < b){
System.out.println("첫 번째 변수가 두 번째 변수보다 작습니다");
}
System.out.println("이 문장은 도달할 수 없습니다");
}
}
public class Demo{
public static void main(String args[]){
Demo_example my_instance = new Demo_example();
my_instance.display_msg();
}
}실행 결과
"첫 번째 변수가 두 번째 변수보다 작습니다" 가 무한히 출력됨
코드 설명
Demo_example이라는 클래스는 두 개의 인스턴스 변수 a(값 2)와 b(값 3)를 정의합니다. 이어서 display_msg 메서드 안에서 while (a < b) 조건문으로 두 변수를 비교하는데, 2 < 3은 항상 참이므로 루프 본문의 메시지가 콘솔에 계속 출력됩니다.
여기서 핵심은 a와 b가 final로 선언되지 않았다는 점입니다. 컴파일러 입장에서는 이 변수들의 값이 실행 중에 변경될 가능성이 있으므로, 루프 아래의 System.out.println("이 문장은 도달할 수 없습니다") 문장을 도달 불가능하다고 판단하지 않습니다. 즉, 컴파일 오류 없이 정상적으로 빌드됩니다.
그러나 런타임에는 a와 b의 값이 변하지 않아 조건이 항상 참으로 유지되고, 결과적으로 while 루프가 무한히 반복됩니다. 따라서 루프 뒤에 위치한 문장은 논리적으로 결코 실행되지 않는, 사실상의 '도달 불가능한 문'이 됩니다.
마지막으로 Demo 클래스의 main 메서드에서는 Demo_example 클래스의 인스턴스를 생성하고, 이 인스턴스를 통해 display_msg 메서드를 호출하여 위와 같은 결과를 콘솔에 출력합니다.
참고: final 변수를 사용하면 어떻게 될까?
만약 a와 b를 final int a = 2, b = 3;처럼 final로 선언하면, 컴파일러는 a < b를 컴파일 시점에 true로 확정합니다. 이 경우 루프 뒤의 문장은 컴파일 타임에 도달 불가능한 문으로 진단되어 "unreachable statement" 오류가 발생하며 빌드 자체가 실패합니다. 이 차이를 이해하면 Java 컴파일러의 흐름 분석(flow analysis) 원리를 더 명확하게 파악할 수 있습니다.