
다형성에서 참조형 변수는 이름 그대로 다양한 자식을 대상으로 참조할 수 있다. 그런데 참조하는 대상이 다양하기 때문에 어떤 인스턴스를 참조하고 있는지 확인하려면 어떻게 해야할까?
Parent parent1 = new Parent();
Parent parent2 = new Child();
여기서 Parent는 자신과 같은 Parent의 인스턴스도 참조할 수 있고, 자식 타입인 Child의 인스턴스도 참조할 수 있다. 이때 parent1, parent2 변수가 참조하는 인스턴스의 타입을 확인하고 싶다면 instanceof 키워드를 사용하면 된다.
package poly.basic;
public class CastingMain5 {
public static void main(String[] args) {
Parent parent1 = new Parent();
System.out.println("parent1 호출");
call(parent1);
Parent parent2 = new Child();
System.out.println("parent2 호출");
call(parent2);
}
private static void call(Parent parent) {
parent.parentMethod();
if (parent instanceof Child) {
System.out.println("Child 인스턴스 맞음");
Child child = (Child) parent;
child.childMethod();
}
}
}

call(Parent parent) 메서드를 보자.
이 메서드는 매개변수로 넘어온 parent가 참조하는 타입에 따라서 다른 명령을 수행한다.
참고로 지금처럼 다운캐스팅을 수행하기 전에는 먼저 instanceof를 사용해서 원하는 타입으로 변경이 가능한지 확인한 다음에 다운캐스팅을 수행하는 것이 안전하다.
해당 메서드를 처음 호출할 때 parent는 Parent의 인스턴스를 참조한다.
parent instanceof Child // parent는 Parent의 인스턴스
new Parent() instanceof Child // false
parent는 Parent의 인스턴스를 참조하므로 false를 반환한다.
해당 메서드를 다음으로 호출할 때 parent는 Child의 인스턴스를 참조한다.
parent instanceof Child // parent는 Child의 인스턴스
new Child() instanceof Child // true
parent는 Child의 인스턴스를 참조하므로 true를 반환한다.
참고로 instanceof 키워드는 오른쪽 대상의 자식 타입을 왼쪽에서 참조하는 경우에도 true를 반환한다.
parent instanceof Parent // parent는 Child의 인스턴스
new Parent() instanceof Parent // parent가 Parent의 인스턴스를 참조하는 경우: true
new Child() instanceof Parent // parent가 Child의 인스턴스를 참조하는 경우: true
쉽게 이야기해서 오른쪽에 있는 타입에 왼쪽에 있는 인스턴스의 타입이 들어갈 수 있는지 대입해보면 된다. 대입이 가능하면 true, 불가능하면 false가 된다.
new Parent() instanceof Parent
Parent p = new Parent() // 같은 타입 true
new Child() instanceof Parent
Parent p = new Child() // 부모는 자식을 담을 수 있다. true
new Parent() instanceof Child
Child c = new Parent() // 자식은 부모를 담을 수 없다. false
new Child() instanceof Child
Child c = new Child() // 같은 타입 true
자바 16부터는 instanceof를 사용하면서 동시에 변수를 선언할 수 있다.
package poly.basic;
// Java 16 Patten Matching for instanceof
public class CastingMain6 {
public static void main(String[] args) {
Parent parent1 = new Parent();
System.out.println("parent1 호출");
call(parent1);
Parent parent2 = new Child();
System.out.println("parent2 호출");
call(parent2);
}
private static void call(Parent parent) {
parent.parentMethod();
// Child 인스턴스인 경우 childMethod() 실행
if (parent instanceof Child child) {
System.out.println("Child 인스턴스 맞음");
child.childMethod();
}
}
}

덕분에 인스턴스가 맞는 경우 직접 다운캐스팅 하는 코드를 생략할 수 있다.
출처 : 김영한의 실전 자바 - 기본편
https://www.inflearn.com/course/김영한의-실전-자바-기본편/dashboard