1. switch의 새로운 점
만약 Java 14 이전 버전에서 코드를 작성했다면, switch는 대략 다음과 같았습니다:
switch (day)
{
case MONDAY:
System.out.println("한 주의 시작!");
break;
case FRIDAY:
System.out.println("금요일이다, 야호!");
break;
default:
System.out.println("평범한 날.");
break;
}
겉보기엔 문제없어 보이지만, 다음과 같은 단점이 있습니다:
- break를 잊지 않아야 합니다(그렇지 않으면 다음 case로 “폴스루(fall-through)”가 발생).
- 중복 코드가 많습니다.
- 값을 반환하려면 미리 변수를 선언하고 각 case 안에서 값을 할당해야 합니다.
Java 14+에서 이 문제를 해결했습니다. 이제 switch가 더 편리하고 현대적입니다.
주요 변경 사항:
- Switch가 표현식이 되었습니다 — 이제 값을 반환할 수 있습니다.
- 콜론과 break 대신 화살표 ->를 사용하는 새로운 문법.
- 여러 case를 쉼표로 묶어 동일한 로직을 처리.
- 컴파일러가 모든 분기가 처리되었는지 검사합니다(특히 enum에서).
- 암묵적 폴스루(fall-through) 위험이 없습니다 — 이제는 명시적으로만 가능합니다.
2. switch 표현식 문법
switch (znachenie)
{
case A, B -> rezultat1;
case C -> {
// 여러 동작
yield rezultat2;
}
default -> rezultatPoUmolchaniyu;
}
->와
yield가 있는 switch 표현식 문법
기본 예시
바로 예제로 살펴봅시다. 이제는 switch에서 값을 이렇게 반환할 수 있습니다:
DayOfWeek day = DayOfWeek.MONDAY;
String message = switch (day)
{
case MONDAY, FRIDAY, SUNDAY -> "짧은 주 또는 휴일!";
case TUESDAY -> "화요일은 힘든 날.";
case WEDNESDAY, THURSDAY -> "한 주의 중간!";
case SATURDAY -> "와, 토요일!";
// 모든 경우를 처리하지 않았다면 default가 반드시 있어야 함
default -> "이상한 날이네요...";
};
System.out.println(message);
여기서 일어나는 일:
- switch (day)는 값을 반환하는 표현식입니다.
- 화살표 -> 뒤에 해당 case의 결과가 옵니다.
- 여러 case를 쉼표로 묶을 수 있습니다.
- break가 하나도 없습니다 — Java가 분기 종료 지점을 스스로 압니다.
- 결과를 바로 message 변수에 할당할 수 있습니다.
숫자 예시
int code = 404;
String result = switch (code)
{
case 200 -> "OK";
case 400, 404 -> "클라이언트 오류";
case 500 -> "서버 오류";
default -> "알 수 없는 코드";
};
System.out.println(result);
문자열 예시
String command = "start";
String status = switch (command)
{
case "start" -> "시작!";
case "stop" -> "정지!";
case "pause" -> "일시 중지...";
default -> "알 수 없는 명령";
};
System.out.println(status);
yield가 있는 블록 사용
때로는 하나의 case에서 여러 동작을 하고 싶을 수 있습니다(예: 복잡한 계산이나 로깅). 이때는 { ... } 블록과 키워드 yield를 사용할 수 있습니다:
int n = 7;
String parity = switch (n % 2)
{
case 0 -> "짝수";
case 1 ->
{
System.out.println("홀수가 발견되었습니다: " + n);
yield "홀수";
}
default -> "뭔가 이상함";
};
System.out.println(parity);
중요: 블록 안에는 반드시 yield가 있어야 하며, 이 값이 해당 case의 반환값이 됩니다.
3. 새로운 문법의 장점
break가 필요 없음
기존 switch에서 잊어버린 break는 고통과 미스터리한 버그의 원인이었습니다. 새로운 문법에서는 break가 전혀 필요 없습니다. 각 분기는 자동으로 종료됩니다.
컴파일러가 모든 분기 처리를 검사
enum을 사용하면서 모든 값을 처리하지 않았다면 — default 없이는 컴파일을 통과하지 못합니다. 이는 코드를 더 견고하게 만듭니다.
“폴스루”(fall-through) 없음
기존 switch에서 break를 빼먹으면 실행이 다음 case로 “폴스루”됩니다. 새로운 문법에서는 이것이 불가능합니다(명령문 블록을 쓰고 명시적으로 break를 사용하는 경우를 제외 — 그러나 여기서는 필요하지 않습니다).
코드가 더 간결하고 읽기 쉬움
직접 비교해 보세요:
변경 전:
String result;
switch (status) {
case "OK":
result = "모두 정상";
break;
case "ERROR":
result = "오류";
break;
default:
result = "알 수 없음";
break;
}
변경 후:
String result = switch (status) {
case "OK" -> "모두 정상";
case "ERROR" -> "오류";
default -> "알 수 없음";
};
여러 case — 하나의 로직
case MONDAY, FRIDAY, SUNDAY -> "휴일 또는 짧은 날!";
4. 기존 switch와의 비교
| 특징 | 기존 switch | 새로운 switch |
|---|---|---|
| break 필수 | 예 | 아니오 |
| 폴스루 (fall-through) | 예 | 아니오 |
| 값 반환 가능 | 아니오(변수를 통해서만) | 예(표현식) |
| 여러 case를 콤마로 구분 | 아니오 | 예 |
| 모든 분기 검사 | 아니오 | 예 (특히 enum에서) |
| 간결성 | 코드가 많음 | 짧고 명료함 |
| enum 및 문자열과 함께 사용 | 예 | 예 |
5. enum 및 문자열과의 호환성
enum 예시
다음과 같은 열거형이 있다고 가정해 봅시다:
enum DayOfWeek
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
이를 새로운 switch에서 사용해 봅시다:
DayOfWeek today = DayOfWeek.WEDNESDAY;
String mood = switch (today)
{
case MONDAY -> "일어나기 힘들다...";
case FRIDAY -> "곧 주말이다!";
case SATURDAY, SUNDAY -> "와, 휴식이다!";
default -> "업무일.";
};
System.out.println(mood);
String 예시
String season = "summer";
String activity = switch (season)
{
case "winter" -> "스케이트 타기";
case "summer" -> "호수에서 수영하기";
case "autumn" -> "버섯 따기";
case "spring" -> "새소리 듣기";
default -> "알 수 없는 계절";
};
System.out.println(activity);
6. 기존 switch를 새로운 스타일로 리팩터링
변경 전:
int day = 3;
String dayName;
switch (day)
{
case 1:
dayName = "월요일";
break;
case 2:
dayName = "화요일";
break;
case 3:
dayName = "수요일";
break;
default:
dayName = "알 수 없는 요일";
break;
}
System.out.println(dayName);
변경 후:
int day = 3;
String dayName = switch (day)
{
case 1 -> "월요일";
case 2 -> "화요일";
case 3 -> "수요일";
default -> "알 수 없는 요일";
};
System.out.println(dayName);
또 다른 예: 여러 case — 하나의 로직
int score = 5;
String grade = switch (score)
{
case 5, 6, 7 -> "좋음";
case 8, 9, 10 -> "아주 좋음";
default -> "더 노력 필요";
};
System.out.println(grade);
7. 일반적인 실수와 특징
오류 №1: 모든 분기를 처리하지 않았는데 default가 없음. switch 표현식에서 나열된 case 외의 값이 올 수 있는 타입(예: int 또는 String)을 사용한다면 컴파일러는 default를 요구합니다. enum에서도 모든 값을 처리하지 않았다면 default가 필수입니다.
오류 №2: 블록에서 yield를 잊음. case에서 여러 동작을 하려고 중괄호 블록을 사용할 때는 yield를 잊지 마세요 — 없으면 컴파일 오류가 발생합니다: "Missing yield statement".
오류 №3: 타입 불일치. 모든 switch 표현식의 분기는 동일한 타입의 값을 반환해야 합니다. 그렇지 않으면 컴파일에 실패합니다.
오류 №4: case 값 중복. 동일한 case 값을 두 번 지정할 수 없습니다 — 컴파일러가 즉시 오류를 보고합니다.
GO TO FULL VERSION