[Day 5| Java] 형변환

y♡ding·2024년 10월 18일
0

데브코스 TIL

목록 보기
22/163

⭐️ 자바의 다형성 (Polymorphism)

다형성은 "하나의 객체가 여러 가지 형태를 가질 수 있는 성질"을 의미하며, 자바에서 상속 관계를 기반으로 구현된다. 다형성을 통해 부모 클래스의 참조 변수가 여러 자식 클래스의 객체를 참조할 수 있으며, 오버라이딩된 메서드를 자식 클래스에 맞게 호출할 수 있다.

🤷🏻‍♀️ 다형성을 통해 부모 클래스의 참조 변수가 여러 자식 클래스의 객체를 참조할 수 있다?

부모 클래스 타입의 변수가 여러 자식 클래스 객체를 하나의 타입으로 다룰 수 있다는 것을 의미한다. 즉, 부모 클래스 타입의 변수를 사용하여 다양한 자식 클래스의 인스턴스를 저장하거나 호출할 수 있다는 것이다.

💡 다형성의 핵심 개념

  1. 상속 관계

    • 자식 클래스는 부모 클래스를 상속하여 부모 클래스의 필드와 메서드를 물려받는다. 이로써 부모 클래스 타입의 참조 변수로 자식 클래스를 다룰 수 있다.
  2. 오버라이딩된 메서드 호출

    • 자식 클래스에서 부모의 메서드를 오버라이딩하면, 부모 클래스의 참조 변수를 사용해도 자식 클래스의 메서드가 호출된다. 즉, 부모 타입으로 참조하더라도 실제 객체의 타입에 맞는 메서드가 실행된다.
  3. 참조 자료형의 형변환

    • 업캐스팅: 자식 클래스의 객체를 부모 클래스 타입으로 자동 변환(형변환)하는 것. 부모 클래스의 참조 변수가 자식 객체를 참조할 수 있다.
    • 다운캐스팅: 부모 클래스 타입으로 참조된 객체를 다시 자식 클래스 타입으로 변환하는 것. 명시적으로 형변환이 필요하며, 올바른 객체를 참조하고 있어야만 가능하다.

📌 업캐스팅 / 다운캐스팅

다형성(Polymorphism)은 자바의 상속 구조에서 중요한 개념으로, 상속 관계에 있는 클래스에서 형변환을 통해 다양한 형태로 객체를 다룰 수 있게 해준다. 업캐스팅다운캐스팅은 이러한 다형성을 구현하는 데 사용되는 형변환 기법이다.

💡 형변환의 기본 개념

  • 형변환은 기본적으로 참조형 변수상속 관계에 있을 때 서로 간의 타입 변환이 가능하다.
  • 상속 관계에 없는 클래스는 형변환이 불가능하지만, 부모-자식 관계에 있는 클래스끼리는 형변환이 가능하다.

예시 코드

class Parent { }
class Child extends Parent { }
class Unrelated { }

Parent p = new Parent();
Child c = new Child();
Unrelated u = new Unrelated();

// 형변환 가능
p = c;  // 자식 -> 부모 (업캐스팅)

// 형변환 불가
// p = u;  // 컴파일 에러 (상속 관계가 없기 때문에 형변환 불가)

1️⃣ 업캐스팅 (Upcasting)

  • 자식 타입을 부모 타입으로 변환하는 것을 말한다.
  • 업캐스팅은 항상 안전하며, 자동으로 형변환된다. 즉, 자식 객체를 부모 타입의 참조 변수로 참조할 수 있다.
  • 하지만, 업캐스팅을 하면 부모 클래스의 메서드와 필드만 사용할 수 있으며, 자식 클래스에 추가된 메서드나 필드는 접근할 수 없다.

🤞🏻 특징

  • 자동 변환: 형변환 연산자 없이 자동으로 변환된다.
  • 다형성: 부모 타입의 참조 변수로 자식 객체를 참조하여 자식 클래스의 오버라이딩된 메서드를 호출할 수 있다.

예시 코드

class Parent {
    void show() {
        System.out.println("Parent의 메서드");
    }
}

class Child extends Parent {
    void show() {
        System.out.println("Child의 메서드");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent p = new Child();  // 업캐스팅
        p.show();  // 자식 클래스의 오버라이딩된 메서드 호출 -> "Child의 메서드"
    }
}
  • 업캐스팅을 통해 자식 객체를 부모 참조 변수로 참조하지만, 자식 클래스에서 오버라이딩된 메서드가 호출된다.

2️⃣ 다운캐스팅 (Downcasting)

  • 부모 타입을 자식 타입으로 변환하는 것을 말하며, 명시적인 형변환이 필요하다.
  • 다운캐스팅항상 안전하지 않으며, 부모 참조 변수가 실제로 자식 객체를 가리키고 있을 때만 가능하다.
  • 그렇지 않으면 ClassCastException이 발생한다. 따라서, 형변환 전에 instanceof 연산자로 타입을 체크하는 것이 안전하다.

🤞🏻 특징

  • 명시적 변환: 형변환 연산자를 사용하여 명시적으로 변환해야 한다.
  • 실제 객체 타입에 의존: 부모 참조 변수가 실제로 어떤 객체를 참조하고 있는지에 따라 다운캐스팅이 성공할지 실패할지 결정된다.

예시 코드

class Parent {
    void show() {
        System.out.println("Parent의 메서드");
    }
}

class Child extends Parent {
    void play() {
        System.out.println("Child의 메서드");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent p = new Child();  // 업캐스팅
        // p.play();  // 컴파일 에러: Parent 타입으로 play() 호출 불가
        
        // 다운캐스팅
        Child c = (Child) p;  // 부모 -> 자식 (명시적 다운캐스팅)
        c.play();  // "Child의 메서드" 출력
    }
}
  • Parent 타입의 참조 변수 p는 실제로 Child 객체를 가리키고 있으므로 다운캐스팅이 가능하며, 다운캐스팅 후 자식 클래스의 메서드인 play()를 호출할 수 있다.

🚨 **ClassCastException 발생

다운캐스팅이 잘못된 객체로 시도되면 런타임 에러가 발생

public class Main {
    public static void main(String[] args) {
        Parent p = new Parent();
        Child c = (Child) p;  // 런타임 에러: ClassCastException
    }
}

⛑️ 안전한 다운캐스팅 (instanceof 사용)

if (p instanceof Child) {
    Child c = (Child) p;
    c.play();
}
  • instanceof 연산자를 사용하여 참조 변수가 실제로 자식 타입의 객체인지 확인한 후 다운캐스팅을 진행하면 안전하다.

⛑️ instanceof 키워드

object instanceof Type
  • object: 확인할 객체
  • Type: 클래스나 인터페이스
  • 결과: true 또는 false로, 객체가 해당 클래스나 인터페이스의 인스턴스인지 여부를 반환

사용 목적

  1. 형변환 가능 여부 확인
  2. 객체의 타입 확인

🥊 업캐스팅과 다운캐스팅 비교

항목업캐스팅 (Upcasting)다운캐스팅 (Downcasting)
설명자식 클래스를 부모 클래스로 형변환.부모 클래스를 자식 클래스로 형변환.
형변환 방식자동 형변환 가능 (형변환 생략 가능).명시적 형변환 필요 ((자식클래스) 형식).
안전성항상 안전하며, 오류가 발생하지 않음.자식 객체를 참조하지 않으면 ClassCastException 발생 가능.
사용 범위부모 클래스의 멤버(필드/메서드)만 접근 가능.자식 클래스의 멤버(필드/메서드)에 접근 가능.
오버라이딩 메서드부모 타입으로 호출해도 자식 클래스의 오버라이딩된 메서드 호출.다운캐스팅 후 자식 클래스의 메서드나 필드에 접근 가능.


👩🏻‍💻 업캐스팅과 다운캐스팅의 사용

상속 관계에서의 다형성

class Animal {
    void sound() {
        System.out.println("동물 소리");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("멍멍");
    }

    void bark() {
        System.out.println("짖다");
    }
}

class Cat extends Animal {
    @Override
    void sound() {
        System.out.println("야옹");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a = new Dog();  // 업캐스팅 (자동 형변환)
        a.sound();  // "멍멍" (오버라이딩된 메서드 호출)
        
        // 다운캐스팅
        if (a instanceof Dog) {
            Dog d = (Dog) a;  // 안전한 다운캐스팅
            d.bark();  // "짖다"
        }

        // 잘못된 다운캐스팅 (런타임 에러)
        // Cat c = (Cat) a;  // ClassCastException 발생
    }
}
  • 업캐스팅을 통해 Animal 타입으로 자식 객체를 다루며, 다형성을 통해 오버라이딩된 메서드를 호출할 수 있다.
  • 다운캐스팅을 통해 자식 클래스의 고유 메서드에 접근할 수 있다.

  • 업캐스팅항상 가능하고, 부모 클래스의 참조 변수자식 객체를 참조할 수 있다.

  • 다운캐스팅명시적인 형변환이 필요하며, 참조 변수가 실제로 가리키고 있는 객체가 자식 클래스여야만 가능하다. 안전한 다운캐스팅을 위해 instanceof 연산자로 타입을 확인하는 것이 좋다.

0개의 댓글

관련 채용 정보