버그는 switch 문의 첫 번째 case에 있습니다. case 끝에 break 문이 없죠. 즉 switch는 두 번째 case를 실행합니다. 첫 번째 case는 실패하고 항상 cruiseControl.grantAccess()를 실행하겠죠.
switch 문은 이러한 동작으로 악명 높습니다. break 문 또는 블록 끝에 다다라야 실행을 멈추거든요. 어떤 C 스타일 언어든 이와 같은 switch 실행 시맨틱(semantic)을 사용합니다. 자바도 C 언어의 계보를 이어 받았습니다.
switch가 이렇게 동작하는 것은 좀 더 간결하고 길이도 짧은 코드를 작성할 수 있기 때문입니다. switch를 쓰면 조건 표현식 몇 개를 평가하지 않아도 되거든요. 심지어 자바 7부터는 switch 문에서 정수, 문자, enum(열거형)뿐만 아니라 문자열도 쓸 수 있게 되었습니다.
하지만 지난 수년 간 득보다 실이 많았고 break 문을 빠뜨려 야기된 버그도 매우 많았습니다. 간혹 의도적으로 break를 누락했다면 반드시 주석을 남기는 것이 좋습니다!
버그가 없는 코드를 봅시다.
class BoardComputer { CruiseControl cruiseControl; void authorize(User user) { Objects.requireNonNull(user); switch (user.getRank()) { case UNKNOWN: cruiseControl.logUnauthorizedAccessAttempt(); break; case ASTRONAUT: cruiseControl.grantAccess(user); break; case COMMANDER: cruiseControl.grantAccess(user); cruiseControl.grantAdminAccess(user); break; } } }