본문 바로가기

Study/Java

JDK 12 New Features

반응형

JDK의 버전별 변경 사항은 이곳을 참고하세요.

Spec

Java SE 12 Platform JSR (386)에 정의된 바와 같이 JSR 386 구현이 목표

실제 Spec은 Final Release Specification 문서를 참고해야 함

Final Release Specification Feature summary

전체 JEP Feature 목록은 OpenJDK의 JDK 12 문서로 확인할 수 있다.

Component Feature  
core-libs / java.lang.invoke JVM Constants API  
specification / language Switch Expressions (Preview)  

Switch Expressions (Preview)

해당 기능은 preview 기능이기 때문에 실행 시 --enable-preview 옵션을 추가해야 동작한다.

명령문이나 표현식으로 사용할 수 있도록 switch 문을 확장하고 두 양식 모두 "기존" 또는 "단순화된" 범위 지정 및 제어 흐름 행동을 사용할 수 있게 된다.

이 변경 사항은 pattern matching (JEP 305)을 사용할 수 있는 방법을 준비한다.

이전 switch 구문의 경우 불필요하게 장황하고 누락된 break 문으로 우발적인 오류가 발생하기 쉬웠다.

switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}

이제 "case L ->" 형태로 오른쪽의 코드만 실행된다는 것을 지정할 수 있게 되어 다음처럼 사용할 수 있게 된다.

switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}

"case L ->" 구문의 오른쪽 부분은 표현식, 블록 또는 throw 호출을 할 수 있다.

switch 내의 로컬 변수의 범위가 switch 블록이었던 기존의 불편한 방식이 해결된다.

switch (day) {
    case MONDAY:
    case TUESDAY:
        int temp = ...
        break;
    case WEDNESDAY:
    case THURSDAY:
        int temp2 = ...     // Why can't I call this temp?
        break;
    default:
        int temp3 = ...     // Why can't I call this temp?
}

위처럼 switch 블록 내 로컬 변수를 외부에서 쓸 수 없어서 아래처럼 사용했었다.

int numLetters;
switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        numLetters = 6;
        break;
    case TUESDAY:
        numLetters = 7;
        break;
    case THURSDAY:
    case SATURDAY:
        numLetters = 8;
        break;
    case WEDNESDAY:
        numLetters = 9;
        break;
    default:
        throw new IllegalStateException("Wat: " + day);
}

이제 다음처럼 사용할 수 있다.

int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};

"case L ->" 오른쪽이 단일 표현식으로 처리되지 않는 경우 블록 구문과 break 반환 값 설정을 사용하면 된다.

int j = switch (day) {
    case MONDAY  -> 0;
    case TUESDAY -> 1;
    default      -> {
        int k = day.toString().length();
        int result = f(k);
        break result;
    }
};

위의 경우 case에 해당하지 않으면 default에서 블록 내 여러 줄의 처리를 수행한 후 break에서 result를 반환하고 있다.

하지만 이로 인해 각 case에서 반환할 값을 break로 지정하지 않은 경우 어떻게 처리해야 하는가와 같은 새로운 문제가 발생하게 된다.

int i = switch (day) {
    case MONDAY -> {
        System.out.println("Monday"); 
        // ERROR! Block doesn't contain a break with value
    }
    default -> 1;
};
i = switch (day) {
    case MONDAY, TUESDAY, WEDNESDAY: 
        break 0;
    default: 
        System.out.println("Second half of the week");
        // ERROR! Group doesn't contain a break with value
};

for문과 같이 사용하는 경우 switch 구문 내에서 continue 가 switch의 구문 실행을 뛰어넘을 수 없게 된다.

for (int i = 0; i < MAX_VALUE; ++i) {
        int k = switch (e) { 
            case 0:  
                break 1;
            case 1:
                break 2;
            default: 
                continue z; 
                // ERROR! Illegal jump through a switch expression 
        };
    ...
}

 

반응형