minOS

자바의 정석 ch7-26 instanceof 연산자 본문

TIL/남궁성의 자바의 정석

자바의 정석 ch7-26 instanceof 연산자

minOE 2023. 12. 21. 21:23
728x90

ch7-26 instanceof 연산자

- 참조변수 형변환 가능 여부 확인에 사용 , 가능하면 true 반환
- 형변환 전에 반드시 instaceof로 확인해야함
class Car{
    String color;
    int door;

    void drive(){
        System.out.println("drive,brrr~");
    }
    void stop(){
        System.out.println("stop!!");
    }
}

class FireEngine extends Car{
    void water(){
        System.out.println("water!!");
    }
}

public class Main {
    // doWork 메소드 설명:
    // - Car 타입의 객체를 매개변수로 받아서 처리합니다.
    // - 만약 받은 객체가 FireEngine의 인스턴스이면, FireEngine으로 명시적 형변환 후 water 메소드를 호출합니다.
    // - 형변환이 불가능한 경우, Car 클래스의 drive 메소드를 호출합니다.
    void doWork(Car c) {
        if (c instanceof FireEngine) {
            // 1. 형변환 가능 여부 확인
            //   - 만약 객체 c가 FireEngine의 인스턴스이면, 형변환 가능
            //   - instanceof 연산자를 사용하여 확인
            FireEngine fe = (FireEngine) c;
            // 2. 형변환
            //   - 형변환 가능한 경우, FireEngine으로 명시적 형변환
            fe.water();
        } else {
            // - 형변환 불가능한 경우
            // - c는 Car 타입이며 FireEngine으로 형변환할 수 없음
            // - 따라서 Car 클래스의 drive 메소드를 호출
            c.drive();
        }
    }

    public static void main(String[] args) {
        Main main = new Main();

        // 첫 번째 호출: Car 객체 전달
        // - FireEngine으로 형변환 불가능(FireEngine은 Car를 확장하지만, Car의 인스턴스보다 더 많은 멤버를 가지고 있음)
        // - 따라서 Car 클래스의 drive 메소드 호출
        main.doWork(new Car());

        // 두 번째 호출: FireEngine 객체 전달
        // - FireEngine으로 형변환 가능
        // - FireEngine 클래스의 water 메소드 호출
        main.doWork(new FireEngine());
    }
}

출력
두번째 호출에서, Car 타입의 참조변수 c로는 water() 메서드를 호출할 수 없으니까 FireEngine타입으로 바꿔서 water()호출한다.


실제 객체 중요
package ch28_2;

class Car{
    String color;
    int door;

    void drive(){
        System.out.println("drive,brrr~");
    }
    void stop(){
        System.out.println("stop!!");
    }
}

class FireEngine extends Car{
    void water(){
        System.out.println("water!!");
    }
}

public class Main {
    public static void main(String[] args) {
        FireEngine fe = new FireEngine();
        System.out.println(fe instanceof Object);
        System.out.println(fe instanceof Car);
        System.out.println(fe instanceof FireEngine);

    }
}​


출력

FireEngine 클래스는 Car 클래스를 상속하고 있으므로 FireEngine 객체는 Car의 인스턴스이다. 또한, 모든 클래스는 자동으로 Object 클래스를 상속하므로 FireEngine 객체도 Object의 인스턴스이다.

따라서 다음의 가지 instanceof 연산은 모두 true 반환한다.

package ch28_2;

class Car{
    String color;
    int door;

    void drive(){
        System.out.println("drive,brrr~");
    }
    void stop(){
        System.out.println("stop!!");
    }
}

class FireEngine extends Car{
    void water(){
        System.out.println("water!!");
    }
}

public class Main {
    public static void main(String[] args) {
        Car c = new Car();
        System.out.println(c instanceof Object);
        System.out.println(c instanceof Car);
        System.out.println(c instanceof FireEngine);

    }
}

출력

Car 클래스의 인스턴스는 Object 인스턴스이며, 또한 Car 클래스의 인스턴스이지만, FireEngine 클래스의 인스턴스는 아니다.
따라서 다음의  가지 instanceof 연산은 위와 같은 결과를 반환한다.

package ch28_2;

class Car{
    String color;
    int door;

    void drive(){
        System.out.println("drive,brrr~");
    }
    void stop(){
        System.out.println("stop!!");
    }
}

class FireEngine extends Car{
    void water(){
        System.out.println("water!!");
    }
}

public class Main {
    public static void main(String[] args) {
        FireEngine fe = new FireEngine();
        Object obj = (Object)fe; //가능
        Car car =(Car)fe; //가능
        fe = (FireEngine)car; // 가능
        car = new Car();
        obj = (Object) car;//가능
        fe = (FireEngine)car; //ClassCastException 오류 , 형변환 불가능
                              // (실제 인스턴스 클래스의 멤버 개수가 형변환 대상 객체의 클래스 멤버 개수보다 작기때문)


    }
}



정리 
Q. 참조변수의 형변환을 왜 하나요?
A.참조변수를 변경함으로서 사용할 수 있는 인스턴스 멤버의 개수를 조절하기 위해

Q.instanceof 연산자는 언제 사용하는가 ?
A.참조변수를 형변환하기 전에 형변환 가능 여부 확인할 때

 

728x90