if/else 문과 마찬가지로, switch문을 사용하면 조건에 따라 코드를 실행해 프로그램의 흐름을 바꿀 수 있어요.
차이점은 switch문은 원시 타입이나 문자열 표현식의 값을 미리 정의된 상수 값과 비교만 할 수 있다는 점이에요.
switch문을 사용할 때 알아두면 유용한 키워드가 몇 가지 있어요.
switch: 이 키워드로 switch의 구조를 선언해요.
뒤에는 결과를 바꿀 표현식이나 변수가 와요.case: 결과가 될 수 있는 여러 경우를 선언할 때 사용해요.break: break 키워드는 원하는 흐름이 끝나는 지점에서 switch의 실행을 멈출 때 아주 유용해요.
이걸 빼먹으면 프로그램이 계속 실행되면서 예상치 못한 결과로 이어질 수 있어요.default: 이름 그대로, 다른 어떤 case도 표현식의 결과와 일치하지 않을 때 기본 결과로 사용해요.가장 단순한 형태로는 원시 타입이나 문자열 표현식을 검사하고, 그 값을 바탕으로 결정을 내려요. 예를 들어볼까요?
String direction = getDirection();
switch (direction) {
case "left":
goLeft();
break;
case "right":
goRight();
break;
default:
// otherwise
markTime();
break;
}
Java 14부터(그전에는 Java 12와 13에서 프리뷰로 사용할 수 있었어요) "향상된" switch 구현을 사용할 수 있어요.
하나의 case에 여러 값을 지정할 수 있어요.
전통적인 switch문에서는 폴스루를 사용할 수 있어요. 다음 예시에서 case 1과 case 3은 같은 동작을 실행해요.
이렇게 되는 건 case 1에서 break 키워드를 쓰지 않기 때문이에요.
switch (number) {
case 1:
case 3:
// do same stuff
break;
case 2:
// do different stuff
break;
// (...)
}
향상된 switch expression에서는 case에 여러 값을 직접 지정할 수 있어요.
다음 예시를 봐요:
switch (number) {
case 1, 3:
// do stuff
break;
case 2:
// do other stuff
break;
// (...)
}
이제 switch-statement나 switch expression을 작성할 수 있어요.
뭐가 다를까요?
기본적으로 문은 엄격한 로직을 요구하는 반면, 표현식은 값을 반환할 수 있어요.
다음과 같이 하는 대신:
String result = "";
switch (expression) {
case "bob":
result = "bob";
break;
// (...)
}
이렇게 할 수 있어요:
String result = switch (expression) {
case "bob":
yield "bob";
// (...)
}
yield는 switch 표현식에서 쓰인다는 점을 빼면 return처럼 동작해요.
yield가 표현식을 끝내기 때문에 여기서는 break가 필요 없어요.
_switch 문_과 _switch 표현식_의 또 다른 차이점은, _switch 표현식_에서는 모든 경우를 반드시 다뤄야 한다는 거예요.
가능한 모든 값에 대한 case를 두거나, default case를 사용하면 돼요.
: 대신 ->를 사용할 수 있어요.
->를 쓰면 break 키워드를 넣지 않아도 돼요.
두 표기법을 모두 쓸 수 있지만, 하나의 switch 안에서는 한 가지만 사용해야 해요.
switch(expression) {
case 1 -> yield "one"
case 2 -> yield "two"
default: yield "other number" // Removing this will result in a compile error
}
스코프.
전통적인 switch는 전체 switch에 스코프가 하나뿐이라서, 스코프 때문에 예상치 못한 동작이 생길 수 있어요.
switch(expression) {
case 1:
String message = "something";
break;
case 2:
String message = "anything";
break;
// (...)
}
이 예시는 switch 안에서 message가 두 번 선언되기 때문에 동작하지 않아요.
다음과 같이 하면 해결할 수 있어요:
switch (expression) {
case 1: {
String message = "something";
break;
}
case 2: {
String message = "anything";
break;
}
// (...)
}
{}가 case의 스코프를 구분해 주기 때문이에요.
하지만 {}는 필수가 아니라서 직관적이지 않아요.
그런데 새 -> 표기법을 사용하면, 뒤에 단일 문이나 표현식, throw 문, 또는 {} 블록 중 하나가 반드시 와야 해요.
이제 헷갈릴 일이 없어요!
향상된 switch에 대한 더 많은 정보는 이 글과 이 글, 그리고 공식 Oracle 문서에서 찾을 수 있어요.
또한 Java 21에는 Guarded Patterns라는 기능이 추가되어, case 레이블 자체에서 검사를 할 수 있어요.
String dayOfMonth = getDayOfMonth();
String day = "";
return switch (day) {
case "Tuesday" when dayOfMonth == 13 -> "Forbidden day!!";
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" -> "Week day";
case "Saturday", "Sunday" -> "Weekend";
default -> "Unknown";
};
Java 21의 switch 표현식에 대한 더 많은 정보는 이 블로그에서 찾을 수 있어요.