김영한의 실전 자바 - 기본편 강의를 듣고 정리한 내용입니다.
김영한의 실전 자바 - 기본편 강의 | 김영한 - 인프런
김영한 | 실무에 필요한 자바 객체 지향의 핵심 개념을 예제 코드를 통해 쉽게 학습합니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바 문
www.inflearn.com
1. 다형성 시작
1.1 다형성의 의미
- 다형성(Polymorphism) : 다양한 형태, 여러 형태
→ 프로그래밍에서는 한 객체가 여러 타입의 객체로 취급될 수 있는 능력을 의미.
1.2 다형적 참조
(1) 부모는 자식을 담을 수 있음
- 부모 타입은 자식 타입을 담을 수 있으나, 자식 타입은 부모 타입을 담을 수 없다.
- Parent poly = new Child() → O
- 단, 자식의 메서드 호출 안됨. → 호출하려면 캐스팅이 필요.
- Child child = new Parent() → X : 컴파일 오류
- Parent poly = new Child() → O
(2) 다형적 참조
- 같은 타입에 참조를 대입
- Parent parent = new Parent()
- Child child = new Child()
- Parent는 하위 타입도 참조 가능
- Parent poly = new Parent()
- Parent poly = new Child()
- Parent poly = new Grandson() : Child 하위에 손자가 있다면 가능
자바에서 부모 타입은 자신은 물론이고, 자신을 기준으로 모든 자식 타입을 참조할 수 있다. 이것이 바로 다양한 형태를 참조할 수 있다고 해서 다형적 참조라 한다.
(3) 다형적 참조의 한계

- Parent poly = new Child() 처럼 자식을 참조한 상황에서 poly 가 자식 타입인 Child 에 있는 childMethod() 를 호출하면 어떻게 될까?
- Parent 클래스부터 시작해서 필요한 기능을 찾는다.
- 그런데 상속 관계는 부모 방향으로 찾아 올라갈 수는 있지만 자식 방향으로 찾아 내려갈 수는 없다.
- 따라서 childMethod() 를 찾을 수 없으므로 컴파일 오류가 발생한다.
- 이런 경우 childMethod() 를 호출하고 싶으면 어떻게 해야할까? 바로 **“다운 캐스팅”**이 필요하다.
2. 다형성과 캐스팅
2.1 다운 캐스팅
- Parent poly = new Child() 와 같이 부모 타입의 변수를 사용하게 되면 poly.childMethod() 와 같이 자식 타입에 있는 기능은 호출할 수 없다.
- 다운 캐스팅을 통해 해결할 수 있다.
- 부모타입 → 자식타입 변환
package poly.basic; public class CastingMain1 { public static void main(String[] args) { //부모 변수가 자식 인스턴스 참조(다형적 참조) Parent poly = new Child(); //단 자식의 기능은 호출할 수 없다. 컴파일 오류 발생 //poly.childMethod(); //다운캐스팅(부모 타입 -> 자식 타입) Child child = (Child) poly; child.childMethod(); } }
2.2 캐스팅
- 업캐스팅(upcasting): 부모 타입으로 변경
- 다운캐스팅(downcasting): 자식 타입으로 변경
3. 캐스팅의 종류
- 하지만 다운캐스팅 결과를 변수에 담아두는 과정이 번거롭다. 이런 과정 없이 일시적으로 다운캐스팅을 해서 인스턴스에 있는 하위 클래스의 기능을 바로 호출할 수 있다.
3.1 일시적 다운 캐스팅
- 일시적 다운 캐스팅
package poly.basic;
public class CastingMain2 {
public static void main(String[] args) {
//부모 변수가 자식 인스턴스 참조(다형적 참조)
Parent poly = new Child();
//단 자식의 기능은 호출할 수 없다. 컴파일 오류 발생
//poly.childMethod();
//일시적 다운캐스팅 - 해당 메서드를 호출하는 순간만 다운캐스팅
((Child) poly).childMethod();
}
}
3.2 업캐스팅
- 현재 타입을 부모 타입으로 변경하는 것을 업캐스팅이라 한다.
- 업캐스팅은 생략할 수 있다. 다운캐스팅은 생략할 수 없다. 참고로 업캐스팅은 매우 자주 사용하기 때문에 생략을 권장한다.
package poly.basic;
//upcasting vs downcasting
public class CastingMain3 {
public static void main(String[] args) {
Child child = new Child();
Parent parent1 = (Parent) child; //업캐스팅은 생략 가능, 생략 권장
Parent parent2 = child; //업캐스팅 생략
parent1.parentMethod();
parent2.parentMethod();
}
}
업캐스팅은 생략해도 되고, 다운캐스팅은 왜 개발자가 직접 명시적으로 캐스팅을 해야할까?
4. 다운캐스팅과 주의점
4.1 다운 캐스팅이 가능한 경우 vs 불가능한 경우
- 다운캐스팅은 잘못하면 심각한 런타임 오류가 발생할 수 있다.
package poly.basic;
//다운캐스팅을 자동으로 하지 않는 이유
public class CastingMain4 {
public static void main(String[] args) {
Parent parent1 = new Child();
Child child1 = (Child) parent1;
child1.childMethod(); //문제 없음
Parent parent2 = new Parent();
Child child2 = (Child) parent2; //런타임 오류 - ClassCastException
child2.childMethod(); //실행 불가
}
}
Child.childMethod
Exception in thread "main" java.lang.ClassCastException: class poly.basic.Parent
cannot be cast to class poly.basic.Child (poly.basic.Parent and poly.basic.Child
are in unnamed module of loader 'app')
at poly.basic.CastingMain4.main(CastingMain4.java:11)
실행 결과를 보면 child1.childMethod() 는 잘 호출되었지만, child2.childMethod() 는 실행되지 못하고, 그 전에 오류가 발생했다.
parent2 는 Parent 로 생성이 되었다. 따라서 메모리 상에 Child 자체가 존재하지 않는다. Child 자체를 사용할 수 없는 것이다.
- 자바에서는 이렇게 사용할 수 없는 타입으로 다운캐스팅하는 경우에 ClassCastException 이라는 예외를 발생시킨다. 예외가 발생하면 다음 동작이 실행되지 않고, 프로그램이 종료된다. 따라서 child2.childMethod() 코드 자체가 실행되지 않는다.
(1) 캐스팅이 가능한 경우

Child 인스턴스가 존재함
(2) 캐스팅이 불가능한 경우

Child 인스턴스가 없음
4.2 업캐스팅이 안전하고 다운캐스팅이 위험한 이유
- 업캐스팅의 경우 이런 문제가 절대로 발생하지 않는다.
- 왜냐하면 객체를 생성하면 해당 타입의 상위 부모 타입은 모두 함께 생성된다!
- 따라서 위로만 타입을 변경하는 업캐스팅은 메모리 상에 인스턴스가 모두 존재하기 때문에 항상 안전하다.
- 따라서 캐스팅을 생략할 수 있다.
- 반면에 다운캐스팅의 경우 인스턴스에 존재하지 않는 하위 타입으로 캐스팅하는 문제가 발생할 수 있다.
- 왜냐하면 객체를 생성하면 부모 타입은 모두 함께 생성되지만 자식 타입은 생성되지 않는다.
- 따라서 개발자가 이런 문제를 인지하고사용해야 한다는 의미로 명시적으로 캐스팅을 해주어야 한다.
5. instanceof
5.1 instanceof
- 다형성에서 참조형 변수는 이름 그대로 다양한 자식을 대상으로 참조할 수 있다. 그런데 참조하는 대상이 다양하기 때문에 어떤 인스턴스를 참조하고 있는지 확인하려면 어떻게 해야할까?
- Parent parent1 = new Parent()
- Parent parent2 = new Child()
- 여기서 Parent 는 자신과 같은 Parent 의 인스턴스도 참조할 수 있고, 자식 타입인 Child 의 인스턴스도 참조할 수 있다. 이때 parent1 , parent2 변수가 참조하는 인스턴스의 타입을 확인하고 싶다면 instanceof 키워드를 사용하면 된다.
5.2 Java 16 - Pattern Matching for instanceof
- 자바 16부터는 instanceof 를 사용하면서 동시에 변수를 선언할 수 있다.
package poly.basic;
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();
}
}
}
parent1 호출
Parent.parentMethod
parent2 호출
Parent.parentMethod
Child 인스턴스 맞음
Child.childMethod
6. 다형성과 메서드 오버라이딩
다형성을 이루는 또 하나의 중요한 핵심 이론은 바로 메서드 오버라이딩이다. 메서드 오버라이딩에서 꼭! 기억해야 할 점은 오버라이딩 된 메서드가 항상 우선권을 가진다는 점이다. 그래서 이름도 기존 기능을 덮어 새로운 기능을 재정의 한다는 뜻의 오버라이딩이다.
- 오버라이딩 된 메서드는 항상 우선권을 가진다. 오버라이딩은 부모 타입에서 정의한 기능을 자식 타입에서 재정의하는 것이다.
- 만약 자식에서도 오버라이딩 하고 손자에서도 같은 메서드를 오버라이딩을 하면 손자의 오버라이딩 메서드가 우선권을 가진다.
- 더 하위 자식의 오버라이딩 된 메서드가 우선권을 가지는 것이다.
728x90
'Java' 카테고리의 다른 글
[Java] Java 21 특징 (0) | 2025.01.31 |
---|---|
[Java] Java 17 특징 (1) | 2025.01.30 |
[Java] Java 11 특징 (0) | 2025.01.30 |
[실전 자바 - 기본편] 다형성2 (0) | 2024.09.09 |
[Java] Optional 알고 사용하기 (0) | 2024.07.25 |