목차
- 업캐스팅(Upcasting)이란?
- 다운캐스팅(Downcasting)이란?
- instanceof 연산자
- 실전 예제
- 자주 하는 실수와 해결방법
1. 업캐스팅(Upcasting)이란?
정의
자식 클래스 객체를 부모 클래스 타입으로 참조하는 것
기본 예제
java
// 부모 클래스
class Animal {
void eat() {
System.out.println("동물이 먹습니다");
}
void sleep() {
System.out.println("동물이 잡니다");
}
}
// 자식 클래스
class Dog extends Animal {
@Override
void eat() {
System.out.println("강아지가 사료를 먹습니다");
}
void bark() { // Dog만의 고유 메서드
System.out.println("멍멍!");
}
}
public class Main {
public static void main(String[] args) {
// 일반적인 객체 생성
Dog myDog = new Dog();
myDog.eat(); // "강아지가 사료를 먹습니다"
myDog.bark(); // "멍멍!"
// 업캐스팅 (자동 형변환)
Animal myAnimal = new Dog(); // Dog → Animal
myAnimal.eat(); // "강아지가 사료를 먹습니다" (오버라이딩된 메서드)
myAnimal.sleep(); // "동물이 잡니다"
// myAnimal.bark(); // 컴파일 에러! Animal에는 bark()가 없음
}
}
업캐스팅의 특징
- 자동 형변환: 명시적 캐스팅 불필요
- 안전한 변환: 항상 성공 (자식은 부모의 모든 것을 포함)
- 메서드 제한: 부모 클래스에 정의된 메서드만 호출 가능
- 실제 객체 유지: 메모리의 실제 객체는 여전히 자식 클래스
메모리 구조
업캐스팅 전후 비교:
[업캐스팅 전]
Dog myDog = new Dog();
↓
참조변수: Dog 타입
실제객체: Dog 객체
접근가능: eat(), sleep(), bark() ✅
[업캐스팅 후]
Animal myAnimal = new Dog();
↓
참조변수: Animal 타입
실제객체: Dog 객체 (변하지 않음!)
접근가능: eat(), sleep() ✅ bark() ❌
2. 다운캐스팅(Downcasting)이란?
정의
부모 클래스 타입을 자식 클래스 타입으로 변환하는 것
주의사항
- 명시적 캐스팅 필요
- 위험할 수 있음 (ClassCastException 발생 가능)
- instanceof로 체크 필수
다운캐스팅 예제
java
public class CastingExample {
public static void main(String[] args) {
// 1. 업캐스팅
Animal animal = new Dog(); // Dog 객체를 Animal로 참조
animal.eat(); // OK
// animal.bark(); // 컴파일 에러
// 2. 다운캐스팅 (명시적 형변환 필요)
Dog dog = (Dog) animal; // Animal → Dog
dog.bark(); // "멍멍!" - 이제 사용 가능!
// 3. 잘못된 다운캐스팅 (런타임 에러)
Animal pureAnimal = new Animal();
// Dog wrongDog = (Dog) pureAnimal; // ClassCastException!
// 4. 안전한 다운캐스팅 (instanceof 사용)
if (animal instanceof Dog) {
Dog safeDog = (Dog) animal;
safeDog.bark(); // 안전하게 실행
}
}
}
3. instanceof 연산자
instanceof란?
객체가 특정 클래스의 인스턴스인지 확인하는 연산자
java
public class InstanceOfExample {
static void checkAnimal(Animal animal) {
// 다운캐스팅 전 반드시 체크!
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark();
} else if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.meow();
} else {
System.out.println("일반 동물입니다");
}
}
public static void main(String[] args) {
checkAnimal(new Dog()); // "멍멍!"
checkAnimal(new Cat()); // "야옹~"
checkAnimal(new Animal()); // "일반 동물입니다"
}
}
4. 실전 예제
게임 캐릭터 시스템
java
// 기본 캐릭터 클래스
abstract class Character {
protected String name;
protected int hp;
public Character(String name, int hp) {
this.name = name;
this.hp = hp;
}
abstract void attack();
void move() {
System.out.println(name + "이(가) 이동합니다");
}
}
// 전사 클래스
class Warrior extends Character {
private int armor;
public Warrior(String name) {
super(name, 200);
this.armor = 50;
}
@Override
void attack() {
System.out.println(name + "이(가) 검으로 공격!");
}
void shieldBlock() { // 전사만의 스킬
System.out.println(name + "이(가) 방패로 막기!");
}
}
// 마법사 클래스
class Wizard extends Character {
private int mana;
public Wizard(String name) {
super(name, 100);
this.mana = 200;
}
@Override
void attack() {
System.out.println(name + "이(가) 마법 공격!");
}
void castSpell() { // 마법사만의 스킬
System.out.println(name + "이(가) 화염구 발사!");
}
}
// 게임 매니저
public class GameManager {
// 모든 캐릭터를 관리하는 배열 (업캐스팅 활용)
private Character[] characters = new Character[10];
private int count = 0;
// 캐릭터 추가 (업캐스팅 자동 발생)
void addCharacter(Character character) {
characters[count++] = character;
}
// 모든 캐릭터 공격
void allAttack() {
for (int i = 0; i < count; i++) {
characters[i].attack(); // 각자의 방식으로 공격
}
}
// 특정 스킬 사용 (다운캐스팅 필요)
void useSpecialSkill(int index) {
Character character = characters[index];
if (character instanceof Warrior) {
Warrior warrior = (Warrior) character; // 다운캐스팅
warrior.shieldBlock();
} else if (character instanceof Wizard) {
Wizard wizard = (Wizard) character; // 다운캐스팅
wizard.castSpell();
}
}
public static void main(String[] args) {
GameManager gm = new GameManager();
// 다양한 캐릭터 추가 (업캐스팅)
gm.addCharacter(new Warrior("아서"));
gm.addCharacter(new Wizard("멀린"));
gm.addCharacter(new Warrior("란슬롯"));
// 모든 캐릭터 공격
gm.allAttack();
// 출력:
// 아서이(가) 검으로 공격!
// 멀린이(가) 마법 공격!
// 란슬롯이(가) 검으로 공격!
// 특수 스킬 사용
gm.useSpecialSkill(0); // 아서이(가) 방패로 막기!
gm.useSpecialSkill(1); // 멀린이(가) 화염구 발사!
}
}
5. 자주 하는 실수와 해결방법
❌ 실수 1: instanceof 체크 없이 다운캐스팅
java
// 잘못된 코드
Animal animal = new Animal();
Dog dog = (Dog) animal; // ClassCastException!
// 올바른 코드
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
// 안전하게 사용
}
❌ 실수 2: 업캐스팅 후 자식 메서드 호출 시도
java
// 잘못된 코드
Animal animal = new Dog();
animal.bark(); // 컴파일 에러!
// 해결방법 1: 다운캐스팅
Dog dog = (Dog) animal;
dog.bark();
// 해결방법 2: 처음부터 자식 타입으로 선언
Dog dog = new Dog();
dog.bark();
❌ 실수 3: 형제 클래스 간 캐스팅 시도
java
class Cat extends Animal { }
class Dog extends Animal { }
// 잘못된 코드
Cat cat = new Cat();
Dog dog = (Dog) cat; // 컴파일 에러! Cat과 Dog는 형제 관계
// 올바른 방법: 공통 부모를 통한 처리
Animal animal1 = new Cat();
Animal animal2 = new Dog();
업캐스팅 vs 다운캐스팅 비교
구분 | 업캐스팅 | 다운캐스팅 |
방향 | 자식 → 부모 | 부모 → 자식 |
형변환 | 자동 (암묵적) | 명시적 필요 |
안전성 | 항상 안전 | 위험할 수 있음 |
instanceof | 불필요 | 필수 권장 |
사용 시기 | 다형성 구현 | 자식 고유 기능 필요시 |
예시 | Animal a = new Dog() | Dog d = (Dog) animal |
핵심 정리
업캐스팅
- 자동 형변환으로 안전하게 부모 타입으로 변환
- 다형성의 핵심 메커니즘
- 부모 클래스의 메서드만 호출 가능
다운캐스팅
- 명시적 형변환 필요
- instanceof로 안전성 체크 필수
- 자식 클래스의 고유 메서드 사용 가능
실무 팁
- 가능한 업캐스팅을 활용한 다형성 설계
- 다운캐스팅은 꼭 필요한 경우만 사용
- instanceof 체크를 습관화
- 인터페이스와 추상 클래스를 활용한 설계
'Java' 카테고리의 다른 글
Java | 메모리 구조 + static vs 인스턴스 종합 정리 (0) | 2025.10.04 |
---|---|
Java | Hiding (0) | 2025.10.04 |
Java | 정적 변수 vs 정적 메서드 (2) | 2025.10.04 |
Java | static vs 인스턴스 변수 차이점 (0) | 2025.10.04 |
Java | 자바 기본 개념 : 클래스, 객체, 상속 (0) | 2025.09.26 |