[JAVA] 객체의 형 변환

2019. 9. 30. 17:47 JAVA/Java

객체의 형 변환


Java 기본 유형의 데이터들처럼 객체 참조변수의 경우에도 형  변환(casting)이 이루어진다. 서로 다른 클래스 유형으로부터 나온 객체 참조변수들 간의 대입에는 일정한 규칙이 있다.


[JAVA/Java] - [JAVA] 기본 데이터 타입과 변환




1. 객체 형 변환의 개요


Parent parent = new Child();


위의 대입연산에서 왼쪽 항(Parent)과 오른쪽 항(Child)의 객체 유형이 서로 다른 경우, 두 유형이 서로 상속 관계에 있고 왼쪽 객체(Parent)가 오른쪽 객체(Child)의 상위 클래스인 경우에만 내부적인 형 변환이 일어난다. 즉, 하위 클래스에서 상위클래스 유형으로 할당하는 것은 가능하나 그 반대의 경우에는 강제 형 변환을 해야 한다. 그러나 상위 클래스 유형을 하위 클래스 유형으로 강제 형 변환하는 경우에는 할당되는 인스턴스 유형에 따라서 실행 오류가 발생할 수 있다.



 



 A a = new A();

 

 Z z = new Z();


 B b1 = new C();


 C c1 = new B();   => 오류


 C c2 = new X();   => 오류

 

 C c3 = (C)z;        => 오류


 C c4 = (C)a;        => 실행 오류


 C c5 = (C)b1;



2. 오버라이딩(Overriding)된 메소드의 호출


대입연산에 의해 객체의 유형이 변환될 수 있다. 형 변환에 참여한 서로 상속관계에 있는 두 클래스 간에는 동일한 이름의 변수가 존재하거나 메소드가 오버라이딩되어 있을 수 있는데, 이와 같은 경우에 생성된 객체 변수를 통해 멤버에 접근하는 데는 주의해야 할 점이 있다.


변수에 대한 접근은 객체의 유형에 의해 결정되며, 메소드 호출은 new 로 할당된 인스턴스에 의해 결정된다.


 Parent.java

Child.java 

 

public class Parent {

    public int age = 55;
    public String name = "father";
   
    public void print(){
        System.out.println("Parent method :" + age);
        System.out.println("Parent method : " + name);
    }
}

 

public class Child extends Parent{

        public int age = 20;
        public String name = "children";
       
        public void print(){
            System.out.println("Child method :" + age);
            System.out.println("Child method :" + name);
        }
}


위의 Parent 클래스와 Parent 를 상속받은 Child 클래스가 있다.


(1) 상위 클래스 = 상위 클래스


 

public class Objectcasting {

    public static void main(String arg[]){
       
        Parent p1 = new Parent();
       
        p1.print();
        System.out.println("Parent val age : " + p1.age);
        System.out.println("Parent val name : " + p1.name);
    }   
}

 



 - Parent 객체에 new Parent() 인스턴스를 생성하여 대입했기에, 당연히 Parent의 변수와 메소드를 호출한다.



(2) 하위 클래스 = 하위 클래스


 

public class Objectcasting {

    public static void main(String arg[]){
       
        Child c = new Child();
       
        c.print();
        System.out.println("Child val age : " + c.age);
        System.out.println("Child val name : " + c.name);
    }   
}

 





 - 이것도 마찬가지다 Child 객체에 new Child() 인스턴스를 생성하여 대입했기에, 당연히 Chld 변수와 메소드를 호출한다.



(3) 상위 클래스 = 하위 클래스


 

public class Objectcasting {

    public static void main(String arg[]){
       
        Parent p2 = new Child();
       
        p2.print();
        System.out.println("Parent val age : " + p2.age);
        System.out.println("Parent val name : " + p2.name);
    }   
}

 






 - Parent 객체에 new Child() 로 하위 클래스 인스턴스를 생성하여 대입했다.

 print() 메소드의 호출은 Child()에 오버라이딩된 함수를 호출하며, 변수에 접근은 상위 클래스인 Parent에 접근하는걸 볼 수 있다.



(4) 하위 클래스 = (Casting) 상위 클래스


 

public class Objectcasting {

    public static void main(String arg[]){
       
        Child c2 = (Child)new Parent();
       
        c2.print();
        System.out.println("Child val age : " + c2.age);
        System.out.println("Child val name : " + c2.name)} 
}

 - 상위 클래스인 Parent() 클래스를 (Child)로 캐스팅 하여 하위 클래스에 대입했다.

아래 결과와 같이 ClassCastException이 발생한다.




 

public class Objectcasting {

    public static void main(String arg[]){
       
        Parent p2 = new Child();
       
        Child c2 = (Child)p2;
       
        c2.print();
        System.out.println("Child val age : " + c2.age);
        System.out.println("Child val name : " + c2.name)
    }   
}

 


 - 상위 클래스를 캐스팅하여 하위 클래스에 대입했지만, p2 는 하위 클래스 Child() 인스턴스이므로, Casting 하여 대입이 가능하다. 결과는 물론 하위 클래스 Child()의 변수와 메소드를 가져온다.




3. 인터페이스의 형 변환


인터페이스의 경우도 클래스는 클래스가 구현하고 있는 인터페이스 유형으로도 변환할 수 있다. 즉, 왼쪽 항에 있는 인터페이스 유형의 객체 참조변수에 그 인터페이스를 구현하고 있는 클래스의 객체 오른쪽 항에 두어 할당할 수 있다.

이 경우도 클래스의 형 변환과 마찬가지로 인터페이스 유형의 객체 참조변수는 인터페이스에 선언된 요소에만 접근할 수 있으며, 변환된 객체를 가지고 인터페이스를 구현하고 있는 클래스에서 선언한 요소에 접근하면 에러가 발생하게 된다.



출처: https://hyeonstorage.tistory.com/186?category=557602 [개발이 하고 싶어요]