-
JAVA - 다형성 (업케스팅, 다운케스팅, instanceof)Java/JAVA17 2024. 11. 12. 09:57반응형
자바에서 업캐스팅(Upcasting)과 다운캐스팅(Downcasting)은 객체지향 프로그래밍에서 객체의 타입을 변환하는 과정입니다.
업캐스팅 (Upcasting)
업캐스팅은 하위 클래스 객체를 상위 클래스 타입으로 변환하는 것입니다. 자바에서는 업캐스팅이 자동으로 수행되며, 상위 클래스 타입의 변수에 하위 클래스 객체를 할당할 때 이루어집니다. 업캐스팅을 통해 상위 클래스에서 정의된 메서드만 접근할 수 있습니다.
예시코드:
class Animal { void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { void sound() { System.out.println("Dog barks"); } void fetch() { System.out.println("Dog fetches"); } } public class Main { public static void main(String[] args) { Animal animal = new Dog(); // 업캐스팅 animal.sound(); // "Dog barks" 출력 (메서드 오버라이딩에 의해 Dog 클래스의 sound() 메서드 호출) // animal.fetch(); // 컴파일 오류: Animal 타입에서는 fetch() 메서드를 호출할 수 없음 } }
Dog와 Animal이라는 클래스가 존재한다. Animal의 경우는 Dog의 부모 객체이다.
부모와 자식 공통적으로 sound()라는 메서드를 가지고 있지만 구성 내용은 상이하다.
Animal animal = new Dog(); // 업캐스팅 animal.sound(); // "Dog barks" 출력 (메서드 오버라이딩에 의해 Dog 클래스의 sound() 메서드 호출) // animal.fetch(); // 컴파일 오류: Animal 타입에서는 fetch() 메서드를 호출할 수 없음
객체를 생성하여 호출하는 경우 animal객체를 생성하는데 Animal을 타입으로하고 구현체는 Dog를 구현하였다.
이러한 경우 업케이스팅이라고 한다.
animal.fetch()에서 오류가 나는 이유는, 실제 참조하고있는 타입(Animal)의 경우 fetch()메서드가 존재하지 않기때문에 컴파일 오류가 발생하게 된다.
다운캐스팅 (Downcasting)
다운캐스팅은 상위 클래스 타입을 하위 클래스 타입으로 변환하는 것입니다. 다운캐스팅은 명시적으로 형 변환이 필요하며, 객체가 실제로 다운캐스팅하려는 타입인지 확인해야 합니다. 그렇지 않으면 ClassCastException이 발생할 수 있습니다.
예시 코드:
public class Main { public static void main(String[] args) { Animal animal = new Dog(); // 업캐스팅 animal.sound(); // 다운캐스팅 if (animal instanceof Dog) { // 타입 확인 Dog dog = (Dog) animal; dog.fetch(); // "Dog fetches" 출력 } } }
위 코드에서 animal 객체가 실제로 Dog 타입인지 확인한 후에 다운캐스팅을 수행하여 Dog 클래스의 fetch() 메서드를 호출할 수 있습니다.
instanceof 연산자는 자바에서 객체가 특정 클래스 또는 인터페이스의 인스턴스인지 확인하는 데 사용됩니다. 이 연산자는 주로 다운캐스팅을 안전하게 수행하기 위해 사용되며, 객체의 실제 타입을 확인하는 방법으로 자주 활용됩니다.
instanceof 사용 이유
- 안전한 다운캐스팅: 다운캐스팅을 할 때, 객체가 실제로 특정 클래스의 인스턴스인지 확인하지 않으면 ClassCastException이 발생할 수 있습니다. instanceof를 사용하면 캐스팅 전에 객체가 해당 클래스의 인스턴스인지 확인할 수 있어 예외를 예방할 수 있습니다.
- 타입 검사: 객체가 어떤 클래스 또는 인터페이스의 인스턴스인지 확인할 때 유용합니다. 예를 들어, 부모 클래스의 타입으로 객체를 참조하면서, 실제로는 자식 클래스의 특정 기능을 사용하고자 할 때 instanceof를 사용하여 타입을 확인합니다.
instanceof의 동작 원리
- instanceof는 객체의 실제 타입이 특정 클래스(또는 인터페이스)와 일치하는지, 또는 상속 관계에 있는지를 확인합니다.
- A instanceof B라는 표현식에서, A는 객체이고, B는 클래스나 인터페이스입니다. 이 표현식은 A가 B 클래스 타입이거나, B 클래스를 상속받은 하위 클래스의 객체일 때만 true를 반환합니다.
사용 가능한 조건
instanceof가 true를 반환하려면 다음 조건을 만족해야 합니다.
- 상속 관계가 있어야 합니다.
- 객체의 실제 타입이 검사하려는 클래스이거나 그 하위 클래스여야 합니다.
예를 들어 Dog 클래스가 Animal 클래스를 상속받는다고 할 때:
- Dog 타입의 객체는 Animal로 업캐스팅할 수 있습니다.
- Animal 타입의 변수로 참조된 Dog 객체는 instanceof를 사용하여 Dog인지 확인할 수 있습니다.
우측에 있는 타입이 좌측 객체의 상위 클래스이거나 인터페이스여야 합니다. 다시 말해, **우측이 좌측의 부모 타입(상위 클래스)**이어야 합니다.
instanceof의 사용법
형식:
객체 instanceof 클래스명
- 이 표현식은 객체가 지정된 클래스의 인스턴스이면 true를, 그렇지 않으면 false를 반환합니다.
예시 코드
class Animal { void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { void sound() { System.out.println("Dog barks"); } void fetch() { System.out.println("Dog fetches"); } } public class Main { public static void main(String[] args) { Animal animal = new Dog(); // 업캐스팅 animal.sound(); // "Dog barks" 출력 // 다운캐스팅을 하기 전에 타입 확인 if (animal instanceof Dog) { Dog dog = (Dog) animal; // 안전하게 다운캐스팅 dog.fetch(); // "Dog fetches" 출력 } else { System.out.println("The object is not a Dog."); } // 다른 예시 if (animal instanceof Animal) { System.out.println("animal is an instance of Animal."); } } }
instanceof 사용 이유와 장점
- 예외 방지: instanceof 없이 다운캐스팅을 하게 되면 잘못된 타입에 대해 다운캐스팅을 시도할 때 ClassCastException이 발생할 수 있습니다. 이를 방지하려면 instanceof를 사용하여 타입을 확인한 후 안전하게 다운캐스팅을 합니다.
- 조건부 로직 구현: instanceof는 조건문 내에서 타입별로 다른 로직을 실행할 때 유용합니다. 예를 들어, 다형성(Polymorphism)을 이용한 코드에서 객체의 구체적인 타입에 맞는 처리를 할 때 사용됩니다.
주의할 점
- instanceof는 객체가 null일 경우 false를 반환합니다. 따라서 null 체크는 따로 해야 합니다.
if (animal != null && animal instanceof Dog) { // 안전하게 다운캐스팅 }
instanceof는 객체의 타입을 명확하게 구분하고, 예외를 방지하는 중요한 역할을 하므로 자주 사용됩니다.
자바 16이상의 instanceof
자바 16 이상부터 instanceof의 문법이 개선되었습니다. 이제 패턴 매칭(Pattern Matching) 기능이 추가되어, instanceof 연산자와 함께 타입 검사 후 형변환까지 한 줄로 처리할 수 있게 되었습니다. 이로 인해 코드가 더 간결해졌고, 별도의 형변환(casting) 코드가 필요하지 않게 되었습니다.
기존 문법
자바 15 이하에서는 instanceof를 사용한 뒤에 다시 형변환을 해야 했습니다.
if (obj instanceof Dog) { Dog dog = (Dog) obj; // 형변환 필요 dog.fetch(); }
자바 16 이상 - 패턴 매칭 instanceof
자바 16 이상부터는 instanceof와 변수를 선언하여 조건문 안에서 직접 형변환된 객체를 사용할 수 있습니다.
if (obj instanceof Dog dog) { // 형변환을 자동으로 처리 dog.fetch(); // Dog 타입으로 바로 접근 가능 }
예시 코드
class Animal { void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { void sound() { System.out.println("Dog barks"); } void fetch() { System.out.println("Dog fetches"); } } public class Main { public static void main(String[] args) { Animal obj = new Dog(); // 업캐스팅 // 자바 16 이후 패턴 매칭 instanceof 사용 if (obj instanceof Dog dog) { dog.fetch(); // 다운캐스팅 없이 바로 Dog 메서드 사용 가능 } else { System.out.println("The object is not a Dog."); } } }
패턴 매칭 instanceof의 장점
- 간결함: instanceof 조건문 안에서 변수를 선언할 수 있어 코드가 깔끔해집니다.
- 안전성: 형변환을 별도로 하지 않으므로 실수로 잘못된 형변환을 할 위험이 줄어듭니다.
- 가독성: 타입 검사와 변수를 한 번에 선언함으로써, 의도를 명확하게 전달할 수 있습니다.
이처럼 자바 16 이상의 패턴 매칭 instanceof를 사용하면, 타입 검사와 형변환을 동시에 수행할 수 있어 코드가 더 간단하고 안전해집니다.
반응형'Java > JAVA17' 카테고리의 다른 글
[JAVA] - 1.8 -> 17 버전 업그레이드 Base64오류 (0) 2025.06.27 JAVA - Generic을 사용해야하는 이유 (1) 2025.06.12 JAVA - GENERIC 사용방법, 사용이유 파헤치기 (1) 2025.06.10 JAVA - 다형성, 추상메서드, 인터페이스 사용하는 이유 (0) 2024.11.12 JAVA - 다형성 Override (0) 2024.11.12