JEP 375: Pattern Matching for instanceof (Second Preview)

JEP 375: Pattern Matching for instanceof (Second Preview)

Summary

instanceof 연산자에 대한 패턴 일치 로 Java 프로그래밍 언어를 향상시킵니다.
패턴 매칭을 사용하면 프로그램의 공통 논리,
즉 개체에서 구성 요소의 조건부 추출을보다 간결하고 안전하게 표현할 수 있습니다.
이것은 JDK 15 의 미리보기 언어 기능 입니다.

History

instanceof 에 대한 패턴 일치는 2017 년 중반 JEP 305 에서 제안했으며
2019 년 말에 미리보기 언어 기능 으로 JDK 14를 대상으로했습니다.
이 JEP는 추가 피드백을 수집하기 위해 JDK 14의 미리보기와 관련된 변경 사항없이 JDK 15의 기능을 다시 미리 볼 것을 제안합니다.

Motivation

거의 모든 프로그램에는 표현식에 특정 유형이나 구조가 있는지 테스트
한 다음 추가 처리를 위해 해당 상태의 구성 요소를 조건부로 추출하는 일종의 논리가 포함되어 있습니다.
예를 들어 모든 Java 프로그래머는 instanceof-and-cast 관용구에 익숙합니다.

1
2
3
4
if (obj instanceof String) {
String s = (String) obj;
// use s
}

위에는 세가지 작업이 있습니다.

  1. obj가 String 인지 테스트
  2. obj를 String으로 케스팅
  3. 새로운 지역 변수 s 의 선언

이 패턴은 간단하고 모든 Java 프로그래머가 이해하지만 여러 가지 이유로 차선책입니다.
지루합니다.
유형 테스트와 캐스트를 모두 수행하는 것은 불 필요해야합니다 (instanceof 테스트 후 다른 작업은 무엇 입니까?).
이 보일러 플레이트 (특히 유형의 세 가지 발생)는 뒤 String 따르는보다 중요한 논리를 난독 화합니다.
그러나 가장 중요한 것은 반복이 오류가 프로그램에 눈에 띄지 않게 나타날 수있는 기회를 제공한다는 것입니다.

임시 솔루션에 도달하기보다는 Java가 패턴 일치 를 수용 할 때라고 생각합니다.
패턴 매칭을 사용하면 객체의 원하는 ‘모양’을 간결하게 표현하고 ( pattern ) 다양한 문과 표현식에서 해당
‘모양’을 입력 ( 매칭 ) 에 대해 테스트 할 수 있습니다.
Haskell에서 C# 에 이르기까지 많은 언어가 간결성과 안전성을 위해 패턴 일치를 채택했습니다.

Description

패턴 (1)의 조합 술어 대상에 적용하는 것이 가능하고,
(2) 세트 변수 결합 술어가 성공적으로 적용되는 경우에만 타겟으로부터 추출된다.

타입의 시험 패턴은 단일 결합 변수와 함께 타입을 지정하는 술어로 구성된다.

instanceof연산자 ( JLS는 15.20.2 ) 대신 타입의 입력 테스트 패턴을 확장한다.
아래 코드에서 구문 String s은 유형 테스트 패턴입니다.

1
2
3
4
5
if (obj instanceof String s) {
// can use s here
} else {
// can't use s here
}

instanceof 연산자 “일치” 목표 obj는 다음과 같이 입력되는 테스트 패턴에 다음의 경우 obj의 String 예이며, 그럼로 캐스팅 String하고 바인딩 변수 s 에 할당.
바인딩 변수는 if 명령문의 거짓 블록이 아니라 명령문 의 실제 블록의 범위에 if 있습니다.

바인딩 변수의 범위는 지역 변수의 범위와 달리 포함하는 표현식 및 문의 의미에 의해 결정됩니다.

예를 들어,이 코드에서 :

1
2
3
4
5
if (!(obj instanceof String s)) {
.. s.contains(..) ..
} else {
.. s.contains(..) ..
}

실제 블록은 s 포함하는 클래스 필드를 지칭하고, s 잘못된 블록의 결합에 의해 도입 된 변수를 참조 instanceof 연산자.
if문의 조건이 단일보다 복잡해 instanceof지면 바인딩 변수의 범위도 그에 따라 늘어납니다.

예를 들어,이 코드에서 :

1
if (obj instanceof String s && s.length() > 5) {.. s.contains(..) ..}

바인딩 변수 s는 && 연산자 오른쪽의 범위와 실제 블록에 있습니다.
(오른쪽은 instanceof성공하고에 할당 된 경우에만 평가됩니다 s.)

반면에 이 코드에서 :

1
if (obj instanceof String s || s.length() > 5) {.. s.contains(..) ..}

바인딩 변수 s는 || 오른쪽의 범위에 있지 않습니다. 연산자도,
실제 블록의 범위에 있지 않습니다.
( s이 지점에서 둘러싸는 클래스의 필드를 나타냅니다.)

instanceof대상이 null 인 경우 작동 방식 에는 변경 사항이 없습니다 .
즉, 패턴은 obj null이 아닌 경우 에만 일치하고 s에 할당됩니다 .

에서 패턴 일치를 사용 instanceof하면 Java 프로그램에서 명시 적 캐스트의 전체 수가 크게 줄어 듭니다.
더욱이, 형 테스트 패턴은 동등 메서드를 작성할 때 특히 유용합니다.
Effective Java 책 의 항목 10에서 가져온 다음 같음 방법을 고려하십시오 .

1
2
3
4
5
@Override 
public boolean equals(Object o) {
return (o instanceof CaseInsensitiveString) &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}

유형 테스트 패턴을 사용하면 더 명확하게 다시 작성할 수 있습니다.

1
2
3
4
5
6
@Override 
public boolean equals(Object o) {
return (o instanceof CaseInsensitiveString cis) &&
cis.s.equalsIgnoreCase(s);
}

instanceof 문법 따라 확장 :

RelationalExpression:

RelationalExpression instanceof ReferenceType
RelationalExpression instanceof Pattern

Pattern:
ReferenceType Identifier

Future Work

향후 JEP는 switch표현식 및 명령문과 같은 다른 언어 구조에 대한 패턴 일치를 통해 Java 프로그래밍 언어를 향상시킬 것 입니다.

Alternatives

형 테스트 패턴의 혜택을 얻을 수있는 흐름 입력 에 if문, 또는에 의해 식 스위치 구조. 패턴 일치는이 두 구조를 모두 일반화합니다.

참조