자바

jdk pattern matching for instanceof

알쓸개잡 2023. 8. 26.

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

댓글

💲 추천 글