캐스팅
자바에서 캐스팅(casting)은 한 타입의 객체 참조를 다른 타입의 객체 참조로 변환하는 과정을 말합니다. 특히 객체지향 프로그래밍에서 상속 관계에 있는 클래스들 사이에서 이루어지는 캐스팅은 중요한 개념입니다. 캐스팅은 크게 업 캐스팅(upcasting), 다운 캐스팅(downcasting)으로 구분 됩니다.
업 캐스팅 (Upcasting)
업 캐스팅은 서브 클래스(subclass, 자식)의 인스턴스를 슈퍼 클래스 (superclass, 부모) 타입으로 변환 하는 것을 말합니다.
업 캐스팅은 안전하며, 자바에서 명시적으로 캐스팅을 하지 않아도 자동으로 수행됩니다. 흔히 말하는 "부모는 자식을 품을 수 있다" 로 생각 하지면 됩니다.
class Animal {
public void eat() {
System.out.println("동물이 먹는다.");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("개가 짖는다.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
// 업 캐스팅, 자동으로 이루어짐
// 자식 Dog 객체가 부모 객체로 업 캐스팅
// 이때 실제 강제 변환을 하지 않아도 자바에서 자동으로 캐스팅
// -> Animal animal = (Animal) dog;
Animal animal = dog;
animal.eat(); // 가능
// 컴파일 에러, Animal 클래스에는 bark 메소드가 없음
// animal.bark();
}
}
다운 캐스팅 (Downcasting)
다운 캐스팅은 업 캐스팅의 반대 과정으로, 슈퍼클래스(부모)의 인스턴스를 서브 클래스(자식) 타입으로 변환하는 것을 말합니다.
다운 캐스팅은 명시적으로 수행해야 하며(캐스팅 대상을 지정해야 합니다) 안전하지 않습니다. 실제 객체 타입의 타입과 캐스팅 하려는 타입이 일치하지 않으면 "ClassCastException"이 발생할 수 있습니다.
public class Main1 {
public static void main(String[] args) {
Animal animal = new Dog();
// 컴파일 에러, Animal 클래스에는 bark 메소드가 없음
// animal.bark();
// 다운 캐스팅, 명시적으로 필요
Dog dog = (Dog) animal;
dog.bark();
// 이렇게도 가능
((Dog) animal).bark();
// 실제 animal 객체의 참조값은 바뀌지 않습니다.
animal.eat(); // 가능
}
}
다운 캐스팅시 확인
다운 캐스팅은 실제 객체 타입을 정확히 알고 있을 때만 사용해야 하며, instanceof 연산자를 통해서 실제 객체 타입을 확인한 후 다운 캐스팅을 하는 것이 안전합니다.
예를들어 위에 소스에서 처럼 Animal animal = new Dog(); 로 인스턴스를 생성하고 animal 인스턴스와 dog 인스턴스 참조값을 비교하면 동일 합니다. ( animal : 5305068a, dog : 5305068a )
그러므로 아래 코드에서 객체 타입을 비교하면 동일한 객체로 판단하게 됩니다.
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark();
}
다운 캐스팅시 예외 발생 ( ClassCastException
해당 예외가 발생하는 주된 원인은 객체가 캐스팅 하려는 객체와의 실제 타입이 호환되지 않는 다른 타입으로 강제로 캐스팅 하려고 하기 때문입니다. 이 예외는 주로 다운 캐스팅 과정에서 발생합니다.
이유는 자식 타입으로 객체를 생성해서 다운 캐스팅을 하게되면
Dog dog = new Dog(); or Animal animal = new Dog(); 부모 클래스도 함께 인스턴스가 생성이 되면 같은 참조 값을 가지지만
public Child extends Parent {
public Child() {
super(); // 부모 인스턴스 생성
}
}
부모 인스턴스로 생성을 하게 되면 부모는 자식을 모릅니다. 그러므로 아래와 같이 다운 캐스팅 예외가 발생하게 됩니다.
public class Main {
public static void main(String[] args) {
// Animal 타입의 객체 생성
Animal animal = new Animal();
try {
// 다운 캐스팅 시도, ClassCastException 발생
Dog dog = (Dog) animal;
dog.bark();
} catch (ClassCastException e) {
System.out.println("다운 캐스팅 실패: " + e.getMessage());
}
}
}
위 코드가 발생하는 원인에 대해서 간단하게 그림으로 표현해 보겠습니다.
'자바' 카테고리의 다른 글
함수형 프로그래밍과 일급객체 (0) | 2024.01.31 |
---|---|
내부 클래스 ( inner class ) 란? (0) | 2024.01.02 |
final, 상수 (0) | 2023.12.14 |
static (0) | 2023.12.13 |
자바 메모리 구조 (0) | 2023.12.13 |