본문 바로가기
java/개념

업캐스팅과 다운캐스팅(+instanceof 연산자)

by unhyepnhj 2024. 5. 22.

업캐스팅(upcasting): 서브 클래스 객체에 대한 레퍼런스를 슈퍼 클래스 타입으로 변환

- 자바에서 서브 클래스 객체는 슈퍼 클래스의 멤버를 모두 가짐

- 서브 클래스의 객체를 슈퍼 클래스의 객체로 취급 가능

- 업캐스팅은 슈퍼 클래스의 레퍼런스로 서브 클래스의 객체를 가리키게 함

class Person{...}
class Student extends Person{...}
public class Main{
    public static void main(String[] args){
        Person p;
        Student s = new Student();
      	p = s;		//업캐스팅
    }
}

슈퍼 클래스인 Person 타입의 p가 서브 클래스인 Student의 객체를 가리키게 되지만, p를 Person 타입으로 선언했으므로 p는 Person 클래스의 멤버에만 접근 가능 


다운캐스팅(downcasting): 슈퍼 클래스 객체의 레퍼런스를 서브 클래스 타입으로 변환

- 업캐스팅과 반대

- 업캐스팅되었던 객체의 자료형을 되돌림

- 개발자의 명시적 타입 변환 필요

class Person{...}
class Student extends Person{...}
public class Main{
	public static void main(String[] args}{
    	Person p = new Student("홍길동");	//업캐스팅
        Student s;
        
        s = (Student)p;		//다운캐스팅, (Student)의 명시적 타입 변환
    }
}

Person p=new Student("홍길동"); 코드를 통해 Student 객체를 Person 타입의 레퍼런스 p로 가리키므로 업캐스팅

s=(Student)p; 코드로 Person 타입의 p를 Student 타입의 레퍼런스 s로 변환하였으므로 다운캐스팅

s를 통해 Student 객체 전체에 접근 가능


이 개념이 너무 어려웠다

시험 당일 아침까지도 이해를 못 해서 그냥 업캐스팅은 슈퍼 클래스가 먼저, 다운캐스팅은 서브 클래스가 먼저 이런 식으로 형식만 외우고 들어갔던 기억이 난다;

SuperClass s1 = new SubClass();		//서브 클래스를 슈퍼 클래스로 형변환
SubClass s2 = (SubClass)s1;		//슈퍼 클래스를 서브 클래스로 형변환

우변의 데이터 타입을 좌변의 데이터 타입으로 변환한다고 생각하면 된다

Student s = new Student();
Person p = s;		//업캐스팅

s가 Student 타입으로 선언되고 Student 타입의 메모리가 할당된 서브 클래스 객체이며, 레퍼런스 p는 Person 타입으로 선언된 상황에서

Person p = s;

문을 통해 레퍼런스 p가 객체 s를 가리키도록 치환되었다

 

업캐스팅을 통해 Person 타입의 p는 서브 클래스 객체를 가리키도록 치환되었고

p는 Person 타입으로 선언되었으므로 Person 클래스의 멤버에만 접근할 수 있다 (위 경우에는 grade, department에 접근할 수 없다)

Person p = new Student("홍길동");	//업캐스팅
Student s = (Student)p;			//다운캐스팅

 

위 코드에서 레퍼런스 p는 Person타입으로 선언, Student 타입으로 할당받아 업캐스팅되었다

이때 서브 클래스의 정보를 모두 담을 수 있는 객체 p의 타입이 슈퍼 클래스로 선언된 것을 서브 클래스 Student 타입으로 되돌리는 것이 다운캐스팅이다


업캐스팅과 instanceof 연산자

 

- 슈퍼 클래스는 여러 서브 클래스에 상속

- 업캐스팅된 레퍼런스로 객체의 타입 판단 어려움

- instanceof 연산자를 사용하여 레퍼런스가 가리키는 객체의 타입을 식별

class Person{
	...
}
class Student extends Person{
	...
}
class Researcher extends Person{
	...
}
class Professor extends Researcher{
	...
}
public class Main{
	public static void main(String[] args){
    	Person p = new Person();
        Person p = new Student();	//업캐스팅
        Person p = new Researcher();	//업캐스팅
        Person p = new Professor();	//업캐스팅
    }
}

- 레퍼런스 p가 Person, Student, Researcher, Professor 중 어떤 객체를 가리키는지 알 수 없음

- 이 경우 타입 식별을 위해 instanceof 연산자를 사용


instanceof 연산자 사용 

레퍼런스 instanceof 클래스명

- instanceof 연산자의 결과 값은 boolean 타입

- 레퍼런스가 가리키는 객체가 해당 클래스 타입의 객체이면 true, 아니면 false

- instanceof는 클래스에만 적용

Person jee = new Student();
Person kim = new Professor();
Person lee = new Researcher();

if(jee instanceof Person)	//true
if(jee instanceof Student)	//true
if(kim instanceof Student)	//false
if(kim instanceof Professor)	//true
if(kim instanceof Researcher)	//true
if(lee instanceof Professor)	//false

if(3 instanceof int)	//오류, instanceof는 객체에 대한 레퍼런스만 사용
if("java" instanceof String)	//오류 아님, String은 객체

예제 5-4 아래 코드의 실행 결과

class Person{}
class Student extends Person{}
class Researcher extends Person{}
class Professor extends Researcher{}

public class InstanceOfEx {
	static void print(Person p) {
		if(p instanceof Person) System.out.print("Person ");
		if(p instanceof Student) System.out.print("Student ");
		if(p instanceof Researcher) System.out.print("Researcher ");
		if(p instanceof Professor) System.out.print("Professor ");
		System.out.println();
	}
	public static void main(String[] args) {
		System.out.print("new Student() ->\t");
       		print(new Student());
		System.out.print("new Researcher() ->\t");
       		print(new Researcher());
		System.out.print("new Professor() ->\t");
       	 print(new Professor());
	}
}

 

'java > 개념' 카테고리의 다른 글

추상 클래스  (0) 2024.05.23
메소드 오버라이딩(+동적 바인딩)  (0) 2024.05.22
상속과 생성자  (0) 2024.05.21
상속과 접근지정자  (0) 2024.05.21
상속  (0) 2024.05.21