Switch Expressions (Standard)
Summary
확장 switch하여 명령문 또는 표현식으로 사용할 수 있도록하여 두 형식 모두
기존 case … :레이블 (전파 포함)
또는 새 case … ->레이블 (전파 없음)을 사용하고,
switch표현 새 레이블을 사용하여 값을 산출합니다.
이러한 switch 변경 사항은 일상적인 코딩을 단순화하고의 패턴 일치 사용 방법을 준비합니다.
이것은 JDK 12 및 JDK 13 의 미리보기 언어 기능 이었습니다 .
History
스위치 표현은 2017 년 12 월 JEP 325에 의해 제안되었습니다 .
JEP 325는 미리보기 기능으로 2018 년 8 월 JDK 12를 대상 으로했습니다 .
JEP 325의 한 가지 측면은 스위치 표현식에서 결과 값을 리턴하기 위해 명령문을 오버로드하는 것입니다 .
JDK 12에 대한 피드백은 이 사용 이 혼란 스럽다고 제안했습니다 .
피드백에 대한 응답으로, JEP 354 는 JEP 325의 진화로 작성되었습니다.
JEP 354는 새로운 성명을 제안하고 의 원래 의미를 복원했습니다.
JEP 354는 2019 년 6 월 JDK 13을 겨냥했습니다.break break yield break 미리보기 기능으로.
JDK 13에 대한 피드백은 스위치 표현식이 JDK 14에서 더 이상 변경되지 않고 최종적이고 영구적이 될 준비가되었음을 제안했습니다.
Motivation
패턴 일치 (JEP 305) 를 지원하기 위해 Java 프로그래밍 언어를 향상시킬 준비를 할 때 기존 switch문장 의
몇 가지 불규칙성 ( 오랫동안 사용자에게 자극을 주었던)이 장애가됩니다.
여기에는 스위치 레이블 사이의 기본 제어 흐름 동작 (통과),
스위치 블록의 기본 범위 지정 (전체 블록이 하나의 범위로 처리됨) 및 switch 더 자연스럽지만
명령문으로 만 작동 하는 사실이 포함 됩니다.
다 방향 조건을 표현식으로 표현하십시오.
현재 Java switch문장 의 설계는 C 및 C ++와 같은 언어를 밀접하게 따르며 기본적으로 시맨틱를 지원합니다.
이 전통적인 제어 흐름은 switch높은 수준의 컨텍스트에서 사용되는
낮은 수준의 코드 (예 : 이진 인코딩 파서)를 작성하는 데 유용 하지만 오류가 발생하기 쉬운 특성이 유연성을 능가하기 시작합니다.
예를 들어, 다음 코드에서 많은 break 명령문은 불필요하게 장황하게 만들며,이 시각적 노이즈는 종종 오류를 디버그하기 어렵게합니다.
1 |
|
case L ->레이블이 일치하면 레이블 오른쪽에있는 코드 만 실행됨을 나타 내기 위해 새로운 형식의
스위치 레이블 “case L ->” 을 도입 할 것을 제안합니다 .
또한 사례 당 여러 상수를 쉼표로 구분하여 허용 할 것을 제안합니다.
이전 코드를 작성할 수 있습니다 :
1 |
|
“ case L ->”스위치 레이블 의 오른쪽에있는 코드 는 표현식, 블록 또는 (편의를 위해) throw명령문으로 제한됩니다.
이는 arms 이 로컬 변수를 도입해야하는 즐거운 결과를 가져 오며 블록에 포함되어야하고
따라서 스위치 블록의 다른 arms 에 대한 범위에 속하지 않습니다.
이것은 지역 변수의 범위가 전체 블록 인 전통적인 스위치 블록에 대한 또 다른 성가심을 제거합니다.
1 | switch (day) { |
기존의 많은 switch 명령문은 본질적으로 switch표현식의 시뮬레이션으로, 각 팔은 공통 대상 변수에 지정하거나 값을 반환합니다.
1 |
|
이것을 진술로 표현하는 것은 우회적이며 반복적이며 오류가 발생하기 쉽습니다.
저자는 numLetters매일 의 가치를 계산해야한다고 표현했습니다 .
보다 명확하고 안전한 switch expression을 사용하여 직접 말할 수 있어야합니다 .
1 | int numLetters = switch (day) { |
결과적으로 switch표현식을 지원하도록 확장 하면 흐름 분석 확장
(표현식이 항상 값을 계산하거나 갑자기 완료해야 함)과 같은 일부 추가 요구 사항이 발생하고
표현식의 일부 사례 switch가 값을 산출하지 않고 예외를 처리 할 수 있습니다.
Description
Arrow labels
case L :스위치 블록의 기존 “ “레이블 외에도 “ “레이블을 사용하여 새로운 단순화 된 양식을 정의합니다
case L ->. 레이블이 일치하면 화살표 오른쪽의 표현식 또는 명령문 만 실행됩니다.
넘어지지 않습니다.
예를 들어, switch새로운 형식의 레이블을 사용하는 다음 명령문이 제공됩니다.
1 | static void howMany(int k) { |
다음 코드 :
1 | howMany(1); |
결과는 다음과 같습니다.
1 | one |
Switch expressions
우리는 switch문장을 표현식으로 사용할 수 있도록 확장합니다 .
예를 들어, 표현식 howMany을 사용 하도록 이전 메소드를 다시 작성할 수 있으므로 switch단일 메소드 만 사용합니다 println.
1 |
|
일반적인 경우 switch식은 다음과 같습니다.
1 |
|
switch식은 폴리 표현이다;
대상 유형이 알려진 경우이 유형은 각 팔로 아래로 밀립니다.
switch식 의 유형은 알려진 경우 대상 유형입니다.
그렇지 않은 경우 독립형 유형은 각 케이스 암의 유형을 결합하여 계산됩니다.
Yielding a value
대부분의 switch표현식에는 “ case L ->”스위치 레이블 오른쪽에 단일 표현식이 있습니다.
전체 블록이 필요한 yield경우 값을 생성하는 새 명령문을 도입 하여 둘러싸는 switch표현식 의 값이됩니다 .
1 |
|
switch표현은 같은 수 switch문, 또한 “전통적인 스위치 블록을 사용하는
case L:”스위치 라벨 (의미를 통해 가을을 의미). 이 경우 새 yield명령문을 사용하여 값이 산출됩니다 .
1 |
|
- break(라벨을 포함하거나 포함하지 않은) 두 개의 진술 yield은 switch진술과 switch표현 사이의 명확한 명확성을 용이하게 한다
- 표현은 switch아니지만 switch표현은 break진술 의 대상이 될 수있다 .
그리고 문장은 switch아니지만 표현은 switch문장의 대상이 될 수 있습니다 yield.
키워드 yield가 아닌 제한된 식별자 (예 var:) yield는 이름 이 지정된 클래스 가 불법 임을 의미합니다 .
yield범위에 단항 메소드가있는 경우 , 표현식 yield(x)은 모호하며
(메소드가 괄호로 묶인 표현식 인 메소드 호출 또는 yield 문일 수 있음),이 모호함은 yield 명령문을 위해 해결됩니다.
메소드 호출이 선호 this되는 경우 인스턴스 메소드 또는 정적 메소드의 클래스 이름으로 메소드를 규정해야합니다 .
Exhaustiveness
switch표현 의 경우 철저 해야합니다 .
가능한 모든 값에 대해 일치하는 스위치 레이블이 있어야합니다. (명쾌하게 switch진술 할 필요는 없습니다.)
실제로 이것은 일반적으로 default조항이 필요함을 의미 합니다.
그러나 enum switch알려진 모든 상수를 포함 하는 표현식 의 경우 default,
enum정의가 컴파일 시간과 런타임 사이에 변경 되었음을 나타내는 절이 컴파일러에 의해 삽입됩니다 .
이 암시 적 default절 삽입 에 의존 하면보다 강력한 코드가 만들어집니다.
이제 코드가 다시 컴파일 될 때 컴파일러는 모든 사례가 명시 적으로 처리되는지 확인합니다.
개발자가 명시 적 default절 (오늘과 마찬가지로)을 삽입 한 경우 가능한 오류가 숨겨져 있습니다.
또한 switch표현식은 값을 사용하여 정상적으로 완료되거나 예외를 발생시켜 갑자기 완료되어야합니다.
이것은 많은 결과를 초래합니다. 먼저, 컴파일러는 모든 스위치 레이블에 대해 일치하는지 확인한 후 값을 얻을 수 있는지 확인합니다.
1 |
|
또 다른 결과는 제어 문,이다 break, yield, return과 continue, 스루 점프 할 수없는 switch등 다음과 같이 표현 :
1 |
|
Dependencies
이 JEP는 JEP 325 및 JEP 354 에서 발전했습니다 . 그러나이 JEP는 독립형이며이 두 JEP에 의존하지 않습니다.
JEP 305로 시작하는 패턴 일치에 대한 향후 지원은 이 JEP를 기반으로합니다.
Risks and Assumptions
레이블이 있는 switch진술 의 필요성 case L ->은 불분명합니다. 다음 고려 사항이 포함을 지원했습니다.
switch부작용으로 운영하지만, 일반적으로 여전히 “라벨 당 하나 개의 행동”이다 문이 있습니다.
새로운 스타일의 레이블을 사용하여 접을 수있게하면 문장이보다 간단하고 오류 발생이 줄어 듭니다.switch문장 블록 의 기본 제어 흐름은 깨지기보다는 넘어가는 것이 Java 역사 초기에
불행한 선택이었으며 개발자에게 계속 큰 문제가되고 있습니다.
표현식 switch뿐만 아니라 일반적으로 구성에 대해이 문제를 해결하면 switch이 선택의 영향이 줄어 듭니다.직교 특징으로 원하는 이점 (표현성, 더 나은 제어 흐름, 더 넓은 범위 지정)을
괴롭 히면 switch표현과 switch진술이 더 공통적 일 수 있습니다.
switch표현과 표현 의 차이가 클수록 switch언어를 배우는 것이 더 복잡해지고 개발자가 스스로 이해하기가 더 예리합니다.