CodeGym /행동 /JAVA 25 SELF /고급 switch 표현식

고급 switch 표현식

JAVA 25 SELF
레벨 10 , 레슨 5
사용 가능

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 값을 두 번 지정할 수 없습니다 — 컴파일러가 즉시 오류를 보고합니다.

1
설문조사/퀴즈
상수, enum 그리고 switch, 레벨 10, 레슨 5
사용 불가능
상수, enum 그리고 switch
상수, enum 그리고 switch
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION