하나의 데이터 타입을 다른 타입으로 바꾸는 것을 타입 변환 혹은 형변환(캐스팅) 이라고 함
자바의 데이터형을 알아보면 크게 두가지로 나뉘게 됨
기본형(primitive) 이든 참조형(referece) 이든 하나의 타입이므로, 서로 타입간의 형변환 가능
상속 관계의 클래스는 크게 부모 클래스(슈퍼 클래스)와 자식 클래스(서브 클래스)로 구분할 수 있는데
, 기본형 타입을 서로 형변환 할 수 있듯이, 자바의 상속 관계에 있는 부모와 자식 클래스 간에는 서로 간의 형변환이 가능
클래스는 reference 타입으로 분류되니 이를 참조형 캐스팅(업캐스팅 / 다운캐스팅)이라고 불림
자식 클래스는 부모 클래스를 상속하고 있기에 부모 클래스의 멤버를 모두 가지고 있지만
, 반면 반대의 상황은 아님
즉, 참조 변수의 형변환은 사용할 수 있는 멤버의 갯수를 조절하는 것임
class Parent {
String name;
int age;
}
class Child extends Parent {
/*
String name;
int age;
*/
int number;
}
Parent p = new Parent();
Child c = new Child();
Parent p2 = (Parent)c; // 업캐스팅 - 자식에서 부모로
Child c2 = (Child)p2; // 다운캐스팅 - 부모에서 자식으로
업 캐스팅 예시 :
List<int> arr = new ArrayList()<>, ( ArrayList → List로 형 변환 했기 때문 )
자식 클래스가 부모 클래스 타입으로 캐스팅되는 것
캐스팅 연산자 괄호를 생략할 수 있음
부모 클래스로 캐스팅 된다는 것은 멤버의 갯수 감소를 의미, 즉 자식 클래스에서만 있는 속성과 메서드는 실행하지 못한다는 의미
업캐스팅을 하고 메소드를 실행할때, 만일 자식 클래스에서 오버라이딩한 메서드가 있을 경우, 부모 클래스의 메서드가 아닌 오버라이딩 된 메서드가 실행되게 됨
업 캐스팅을 하는 이유
할 필요가 있을까 생각이 들긴 하지만, 다형성을 활용하기 위해서임
업캐스팅은 다형성을 활용하여 코드의 유연성과 재사용성을 높이고, 인터페이스 기반 프로그래밍을 가능하게 하여 유지보수를 쉽게 만듦
public class Zoo {
public void makeAnimalSound(Animal animal) {
animal.sound();
}
}
---
public class Main {
public static void main(String[] args) {
Zoo zoo = new Zoo();
Animal dog = new Dog();
Animal cat = new Cat();
zoo.makeAnimalSound(dog); // 멍멍!
zoo.makeAnimalSound(cat); // 야옹~
}
}
Zoo 클래스는 Animal 타입만 알면 되고, 어떤 동물이 들어오든 유연하게 처리 가능
다운캐스팅은 거꾸로 부모 클래스가 자식 클래스 타입으로 캐스팅 되는 것
다운캐스팅은 캐스팅 연산자 괄호를 생략할 수 없음
다운캐스팅의 목적은 업캐스팅한 객체를 다시 자식 클래스 타입의 객체로 되돌리는 것
( 되돌려서 자식 클래스만의 필드나 메서드를 사용하기 위해 )
부모 객체를 자식 객체로 다운 캐스팅 하는 것은 불가능 ;;
객체가 특정 클래스의 인스턴스인지 확인할 때 사용하는 연산자 ( true, false 반환 )
사용 목적 : 참조 타입 캐스팅 전 안전성 검사, 다운캐스팅 시 ClassCastException 방지
if (animal instanceof Dog) {
Dog dog = (Dog) animal; // 안전하게 다운캐스팅
dog.wagTail();
}
즉, instanceof 연산자는 객체가 특정 클래스의 인스턴스인지 확인하여 안전한 다운 캐스팅을 가능하게 해주는 연산자이며, 참조형 타입에서만 사용할 수 있음