자바 형변환 체크 - jaba hyeongbyeonhwan chekeu

객체간 자료형을 변환하는 것

  • 인터페이스, 배열, 클래스에 적용
  • 상속 관계 때문에 만들어진 기능

Upcasting 묵시적 객체 형 변환

하위 클래스에서 상위 클래스로 자료형을 변환하는 것

  • 하위 클래스는 이미 상위 클래스를 상속받아서
    상위 클래스의 모든 변수와 기능을 가지고 있기 때문에
    하위 클래스의 객체를 상위 클래스의 자료형으로 변환해서 생성할 수 있음
  • 하위 클래스의 객체를 상위 클래스의 자료형으로 선언하기만 하면 됨
  • 상위 클래스형 변수(ex. 배열)에 대입되는 경우에도 묵시적 형 변환이 일어남
  • 상위 클래스형으로 생성된 객체는 상위 클래스의 멤버 변수와 메소드만 사용 가능
    단, 메소드가 하위 클래스에서 오버라이딩되었다면 오버라이딩된 메소드 호출
  • 상위 클래스에서는 하위 클래스로 묵시적 형 변환을 할 수 없음

형식

상위클래스형 하위클래스 객체명 = new 하위클래스형();

// SuperClass sub = new SubClass();

※ 클래스형과 클래스의 자료형, 인스턴스형과 인스턴스 자료형은 모두 비슷한 의미로 사용


예제

package j200205;

// Shape_상위 클래스
class Shape {

    // 모든 도형에서 사용하는 메소드
    void draw() {
        System.out.println("Shape");
    }

    // Shape 전용 메소드
    void shapeDraw() {
        System.out.println("Shape");
    }
}

// Point_하위 클래스
class Point extends Shape {
    // 오버라이딩
    void draw() {
        System.out.println("Point");
    }

    // Point 클래스 메소드
    void pointDraw() {
        System.out.println("Point");
    }
}

public class ShapeTest {

    public static void main(String[] args) {

        // 클래스형에 맞는 객체 생성
        Shape s = new Shape();
        Point p = new Point();

         // 묵시적 형변환_객체 생성
         Shape sp = new Point();

        // 각자 메소드 출력
        s.shapeDraw();    // Shape
        p.pointDraw();    // Point
        sp.shapeDraw();   // Shape
        
        sp.draw();        // Point, 오버라이딩된 메소드가 호출됨
        // sp.pointDraw() 메소드는 호출 불가

        // 묵시적 형변환_배열 요소에 대입
        // 배열에는 같은 자료형만 저장될 수 있는데
        // 하위 클래스 객체는 상위 클래스 배열에 묵시적으로 들어갈 수 있음

        // Shape 자료형 배열 생성 및 초기화
        Shape[] sh = new Shape[3];
        sh[0] = s; // Shape 
        sh[1] = p; // Point
        sh[2] = sp; // Shape

        // 배열에 객체들이 잘 저장됐는지 확인
        for (int i = 0; i < sh.length; i++) {
            sh[i].draw();
        }

        /*
        Shape
        Point
        Point
        */
    }

}

Instanceof

왼쪽에 있는 객체가 오른쪽 클래스의 인스턴스(객체)인지 확인하는 예약어
맞다면 true, 아니라면 false 반환


형식

객체명 instanceof 클래스명

예제

package j200205;

class Shape {

	// 위의 예제와 동일

}

class Point extends Shape {
	
	// 위의 예제와 동일

}


public class ShapeTest {

    // Shape 객체 클래스형 확인 메소드
    static void whoAreYou(Shape sh) {
    
        // 객체가 Shape형인지 확인
        if(sh instanceof Shape)
            System.out.println("I am Shape");
        else
            System.out.println("I am not Shape");
            
        // Point형인지 확인
        if(sh instanceof Point)
            System.out.println("I am Point");
        else
            System.out.println("I am not Point");
            
    }

    public static void main(String[] args) {

        // 객체 생성
        Shape s = new Shape();
        Point p = new Point();
        Shape sp = new Point();

        Shape[] sh = new Shape[3];
        sh[0] = s; // Shape
        sh[1] = p; // Shape + Point
        sh[2] = sp;

        // 객체 자료형 확인
        for (int i = 0; i < sh.length; i++) {
            sh[i].draw();
            whoAreYou(sh[i]);
        }
        
        /*
        Shape
        I am Shape
        I am not Point
        Point
        I am Shape
        I am Point
        Point
        I am Shape
        I am Point
        */
    }

}

※ Shape 클래스로 생성된 객체는 Point 클래스의 객체가 아니지만,
Point 클래스로 생성된 객체는 Point 클래스의 객체이면서 동시에 Shape 클래스 객체임
자동 형 변환으로 생성된 객체 역시 Point 클래스로 생성된 객체이면서 Shape 클래스 객체임


Downcasting 명시적 객체 형 변환

상위 클래스로 생성된 객체를 하위 클래스로 강제로 형 변환하는 것
상위 클래스로 형 변환되었던 하위 클래스를 다시 하위 클래스형으로 형 변환

  • 상위 클래스에서 하위 클래스로 형변환을 할 때는 하위 클래스 자료형을 명시해야 함
  • instanceof 예약어로 상속 관계를 확인하고 형 변환을 해야 실행 오류를 방지할 수 있음
  • 명시적 형 변환시 상속 관계가 아니더라도 클래스 자료형만 맞으면
    컴파일 에러는 발생하지 않지만, 프로그램을 실행하면 실행 에러 발생

형식

하위클래스형 하위클래스 객체명 = (하위클래스형) 상위클래스 객체명;
// SubClass sub = (SubClass) superClass; 

예제

package j200205;

class Shape {

    void draw() {
        System.out.println("Shape");
    }

    void shapeDraw() {
        System.out.println("Shape");
    }
}

class Point extends Shape {

    void draw() {
        System.out.println("Point");
    }

    void pointDraw() {
        System.out.println("Point");
    }
}

public class ShapeTest {

    public static void main(String[] args) {

        // 묵시적 형 변환으로 Shape 형 객체 생성
        Shape sp = new Point();

        if (sp instanceof Point) {
            // sp 객체가 원래 Point 클래스로 생성된 것인지 확인
            System.out.println("Point 클래스 객체!");

            // 명시적 형 변환
            Point pp = (Point) sp;
            pp.pointDraw();
            // Point형 객체가 되었기 때문에 pointDraw() 메소드에 접근 가능
        }
        
        /*
        Point 클래스 객체!
        Point
        */
    }
}

객체 형 변환과 객체의 클래스형을 확인하는 instanceof 예약어에 대해 살펴보았습니다.

객체 형 변환의 경우 자바의 굉장히 많은 곳에서 사용된다고 하기 때문에 꼭 알아둘 필요가 있겠습니다.

묵시적 형 변환시 상위 클래스의 멤버 변수 및 메소드에만 접근할 수 있지만
상위 클래스의 메소드를 하위 클래스에서 재정의한 경우 오버라이딩 메소드가 호출된다는 점이 특이한 것 같습니다.

instanceof의 경우 해당 객체의 클래스형을 확인할 수 있으므로 다양한 경우에서 유용하게 사용할 수 있겠습니다.