자바

java switch expression - from jdk 14

알쓸개잡 2023. 8. 20.

JDK 12 에서 preview 기능으로 새롭게 추가된 switch expression(표현식)이 jdk 14 에서 정식 릴리즈 되었습니다.

이번 포스팅에서는 정식 릴리즈된 switch expression 에 대해서 소개와 사용 방법에 대해서 소개합니다.

JDK14 에 정식 릴리즈된 switch expression 은 JEP 361 에서 제안되었습니다.

기존의 switch 구문(statement) 뿐 아니라 하나의 표현식(expression) 으로써 switch 를 제공합니다.

 

"case L ->" Labels

switch label 이 일치하는 경우 label 오른쪽에 있는 코드만 실행되도록 하는 새로운 형태의 스위치 lable 입니다. "case L ->" 로 표현합니다. 아래 코드는 기존의 switch 구문(statement)을 나타냅니다.

public enum City { SEOUL, NEWYORK, LONDON }

// ...

String countryName;
City city = City.SEOUL;

switch (city) {
    case SEOUL:
        countryName = "Korea";
        break;
    case NEWYORK:
        countryName = "America";
        break;
    case LONDON:
        countryName = "England";
        break;
    default:
        countryName = "unknown";
}

System.out.println(countryName);

도시의 나라 이름을 countryName 변수에 할당하여 출력하는 기존의 switch 구문입니다. 기존의 switch 구문을 사용하는 대신에 countryName 을 리턴하는 switch expression(표현식) 을 사용하면 코드를 더욱 간결하고 효율적으로 개선할 수 있습니다.

아래는 "case L ->" switch expression 을 사용한 코드입니다. 

public enum City { SEOUL, NEWYORK, LONDON }
...

City city = City.SEOUL;
String countryName =
    switch (city) {
        case SEOUL -> "Korea";
        case NEWYORK -> "America";
        case LONDON -> "England";
        default -> "unknown";
    };
System.out.println(countryName);

기존의 코드와 비교해서 더욱 간결하면서도 break 문이 제거됨으로써 break 문의 누락 실수를 방지할 수도 있습니다. 위 switch 문은 statement 가 아닌 expression 임을 알아야 합니다. 그렇게 때문에 값을 리턴할 수도 있습니다.

 

"case L ->" Labels 와 yield

switch expression 에서 yield 는 값을 리턴하는 키워드 입니다.

"case L ->" 문법에서 여러 문장을 사용하는 경우에는 해당 코드를 블록으로 묶고 yield 를 통해 리턴할 수 있습니다.

public enum City { SEOUL, NEWYORK, LONDON }
...

City city = City.SEOUL;
String countryName =
switch (city) {
    case SEOUL -> {
        System.out.println("Korea");
        yield "Korea";
    }
    case NEWYORK -> {
        System.out.println("America");
        yield "America";
    }
    case LONDON -> {
        System.out.println("England");
        yield "England";
    }
    default -> {
        System.out.println("unknown");
        yield "unknown";
    }
};

 

"case L:" Labels 와 yield

"case L ->" 이 아닌 "case L:" 문법에서도 yield 키워드를 사용하여 값을 리턴할 수 있습니다.

public enum City { SEOUL, NEWYORK, LONDON }
...

City city = City.SEOUL;
String countryName =
    switch (city) {
        case SEOUL: yield "Korea";
        case NEWYORK: yield "America";
        case LONDON: yield "England";
        default: yield "unknown";
    };
System.out.println(countryName);

yield 문을 사용하면 switch statement(구문) 와 switch expression(표현식) 을 쉽게 구분할 수 있습니다. switch expression 이 아닌 switch statement 는 break 문의 대상이 될 수 있습니다. 반대로 switch expression 은 반환 문의 대상이 될 수 있습니다.

 

오라클 공식문서에서는 "case L:" 를 사용하는 것보다 "case L ->" expression 을 사용하는 것을 권장합니다. "case L:" 문법을 사용하는 경우 break 혹은 yield 문을 누락하는 실수가 발생할 소지가 있기 때문입니다.

 

Exhaustiveness (완전성)

switch문(statement)과 달리 switch표현식(expression) 은 가능한 모든 값에 대해 일치하는 switch label 이 있어야 합니다. 따라서 switch expression 에는 default 문이 필요합니다. 단 enum 타입과 같이 알려진 상수를 포함하는 switch expression 의 경우 default 문이 없을 때는 컴파일러에서 암묵적으로 default 문을 넣습니다.

 

또한 값을 할당하는 switch expression 이 사용되는 경우에 switch expression 은 반드시 값을 리턴해야 합니다.

String countryName =
    switch (city) {
        //java: incompatible types: bad type in switch expression
        //void cannot be converted to java.lang.String
        //컴파일 error 발생!!
        case SEOUL -> System.out.println("Korea");
        default -> "unknown";
    };

===========

switch (city) {
    //java: not a statement
    //리턴된 값을 할당하는 부분이 없기 때문에 컴파일 error 발생!!
    case SEOUL -> "Korea";
    default -> "unknown";
};
            
===========            

switch (city) {
    //ok
    case SEOUL -> System.out.println("Korea");
    default -> System.out.println("unknown");
};

switch expression에서 단일값(리턴값이 있는) 으로 평가되는 경우에는 break, continue 문을 사용하여 switch expression 을 건널 뛸 수 없습니다. 이 경우에는 예외로 처리를 해야 합니다.

public enum City { SEOUL, NEWYORK, LONDON }
...

for (City city : City.values()) {
    String countryName = switch (city) {
        case SEOUL -> "Korea";
        case LONDON -> "England";
        //java: illegal start of expression compile error!!!
        default -> continue;
    };
    System.out.println(countryName);
}

 

위 코드와 같이 loop 구문 안에서 사용되는 switch expression 은 continue 대신에 예외로 처리를 해야 합니다.

public enum City { SEOUL, NEWYORK, LONDON }
...

for (City city : City.values()) {
    try {
        String countryName =
            switch (city) {
                case SEOUL -> "Korea";
                case LONDON -> "England";
                default -> throw new RuntimeException("not processed, " + city);
            };
        System.out.println(countryName);
    } catch (RuntimeException e) {
        System.out.println(e.getMessage());
    }
}

=====================================

실행결과
Korea
not processed, NEWYORK
England

 

JDK 14 에 정식 릴리즈된 switch expression 에 대한 오라클 공식 문서 링크 남깁니다.

이 글을 읽으시는 분에게 도움이 되었기를 바랍니다.

'자바' 카테고리의 다른 글

jdk pattern matching for switch  (0) 2023.08.26
jdk pattern matching for instanceof  (0) 2023.08.26
java Array vs ArrayList  (0) 2023.08.19
java record 용법 - from jdk 14  (0) 2023.08.19
CompletableFuture 를 알아보자  (0) 2023.08.06

댓글

💲 추천 글