- jdk pattern matching for instanceof2023년 08월 26일
- 알쓸개잡
- 작성자
- 2023.08.26.오후03:43
pattern matching 은 객체가 특정 구조를 가지고 있는지 테스트한 다음 일치하는 경우 해당 객체에서 데이터를 추출하는 작업을 포함합니다. 이번 포스팅에서는 instanceof 연사자에 pattern matching 을 적용 하는 방법에 대해서 기술합니다.
jdk pattern matching
- jdk 14 버전에서 instanceof 연산자에 대한 pattern matching 기능이 JEP 305 를 통해 preview 기능으로 처음 제안됨
- jdk 16 버전에서 instanceof 연산자에 대한 pattern matching 기능이 JEP 394 를 통해 정식 기능으로 릴리즈됨
- jdk 17 버전에서 switch 표현식과 구문에 대한 pattern matching 기능이 JEP 406 을 통해 preview 기능으로 제안됨
pattern matching for instanceof
타입 패턴 형태로 타입 이름과 결과를 바인딩할 변수로 구성됩니다. instanceof 연산자에 타입 패턴을 적용하면 타입 체크와 형변환이 간소화됩니다.
아래와 같은 instanceof 에 대한 기존 코드가 있습니다.
if (obj instanceof String) { String s = (String) obj; .... }
위 코드에는 테스트(obj 가 String 타입인지?), 변환(obj 를 String 으로 형변환), 새로운 지역 변수 선언의 세 가지 작업을 수행합니다. 이미 obj 가 String 타입인지 테스트를 했음에도 명시적으로 형변환을 수행하는 것은 불필요 한 작업이 될 수 있습니다. 가장 중요한 것은 타입에 대한 테스트, 형변환, 지역변수 할당과 같은 반복으로 인해서 눈에 띄지 않는 오류를 발생 시킬 수 있다는 것입니다.
instanceof 에 대한 pattern matching 을 적용한 코드는 아래와 같습니다.
if (obj instanceof String s) { //obj 를 String 타입 변수 s 에 할당한 s 를 사용 }
pattern matching 을 사용하게 되면 명시적인 형변환과 지역변수 정의 및 할당을 제거하여 코드를 간소화 시킬 수 있습니다.
scope of pattern variables
public interface Shape {} public class Rectangle implements Shape {} public class Circle implements Shape {} public class Triangle implements Shape {} ... if (shape instanceof Rectangle r) { //Rectangle 타입의 패턴 변수 r 을 이 영역에서만 사용가능 합니다. } else if (shape instanceof Circle c) { //Circle 타입의 패턴 변수 c 는 이 영역에서만 사용가능 합니다. //Rectangle 타입의 패턴 변수 r 은 이 영역에서는 사용할 수 없습니다. } else { //이 영역에서는 패턴 변수 r, c 모두 사용할 수 없습니다. }
패턴 변수를 정의한 구문 밖으로 패턴 변수는 확장 될 수 있습니다.
public interface Shape { void print(); } public class Rectangle implements Shape {} public class Circle implements Shape {} public class Triangle implements Shape {} ... void scopeTest(Shape shape) { //if 블록 영역 밖이 Rectangle r 패턴 변수를 사용할 수 있는 영역입니다. if (!(shape instanceof Rectangle r)) { //Rectangle 타입의 패턴 변수 r 은 이 블록에서는 사용할 수 없습니다. Sytem.out.println("rectangle 이 아닙니다."); //하지만 아래 return 문이 없다면 if 블럭 밖에서 패턴 변수 r 을 사용할 수 없습니다. //즉 패턴 변수 r 을 사용할 수 있는 영역과 아닌 영역이 명확하게 구분 되어야 합니다. return; } //이 영역에서 패턴 변수 r 을 사용할 수 있습니다. r.print(); } ======================================================================= void scopeTest(Shape shape) { if (!(shape instanceof Rectangle r)) { //패턴 변수 r 을 사용할 수 없는 영역이기 때문에 //cannot find symbol (variable r) 오류 발생!!! r.print(); } } ======================================================================= void scopeTest(Shape shape) { if (!(shape instanceof Rectangle r)) { Sytem.out.println("rectangle 이 아닙니다."); } //패턴 변수 r 을 사용할 수 없는 영역안에 return 문이 없기 때문에 //cannot find symbol (variable r) 오류 발생!!! r.print(); }
if 문 안의 표현식에서 패턴 변수를 사용할 수 있습니다. 각 Rectangle, Triangle, Circle 클래스에 Boolean 타입을 리턴하는 isXXXX() 메소드가 있다고 가정합니다.
void scopeTest(Shape shape) { //패턴 변수 r을 if문 내에서 사용할 수 있습니다. if (shape instanceof Rectangle r && r.isShape()) { r.print(); } //패턴 변수 t를 if문 내에서 사용할 수 있습니다. else if (shape instanceof Triangle t && t.isShape()) { t.print(); } //패턴 변수 c를 if문 내에서 사용할 수 있습니다. else if (shape instanceof Circle c && c.isShape()) { c.print(); } else { throw new IllegalArgumentException(); } } void scopeTest2(Shape shape) { // ||(or) 연사자를 통해서 shape 는 Rectangle 타입이 아닌 경우에도 // r.isShape() 이 호출되기 때문에 컴파일러 오류가 발생합니다. !!! // cannot find symbol (variable r) // symbol: variable r if (shape instanceof Rectangle r || r.isShape()) { ... } }
'자바' 카테고리의 다른 글
Java - 람다 표현식 (lambda expression) 개요 (0) 2023.09.10 jdk pattern matching for switch (0) 2023.08.26 java switch expression - from jdk 14 (0) 2023.08.20 java Array vs ArrayList (0) 2023.08.19 java record 용법 - from jdk 14 (0) 2023.08.19 다음글이전글이전 글이 없습니다.댓글