📝 끄적끄적/🖥️ 자바의 정석

[자바의 정석] 참조변수의 형변환, instanceof 연산자

현주먹 2023. 9. 24. 22:59

참조변수의 형변환

  • 사용할 수 있는 멤버(멤버 변수, 메서드)의 갯수를 조절하는 것

이거 외에는 아무것도 없다!!

주소값이나 객체? 절대 안바뀐다.

 

  • 조상 자손 관계일때만 참조변수 서로 형변환 가능(형제X)
class Car {}
class FireEngine extends Car {}

FireEngine f = new FireEngine();
Car c = (Car)f; //조상인 Car타입으로 형변환(생략가능)

 

예제

class CastingTest1 {
	public static void main(String args[]) {
		Car car = null;
		FireEngine fe = new FireEngine();
		FireEngine fe2 = null;

		fe.water();
		car = fe;    // car =(Car)fe;에서 형변환이 생략된 형태다.
//		car.water();	//컴파일 에러! Car타입의 참조변수로는 water()사용불가

		fe2 = (FireEngine)car; // 자손타입 ← 조상타입. 형변환 생략 불가
		fe2.water();
	}
}

class Car {
	String color;
	int door;

	void drive() { 		// 운전하는 기능
		System.out.println("drive, Brrrr~");
	}

	void stop() {		// 멈추는 기능	
		System.out.println("stop!!!");	
	}
}

class FireEngine extends Car {	// 소방차
	void water() {		// 물을 뿌리는 기능
		System.out.println("water!!!");
	}
}

참조변수가 가리키는 실제 객체의 멤버의 수를 넘으면 안된다.

만약 조상 멤버가 4개고 자식이 5개다.

5개를 넘으면 안된다. 형변환 되고 안되고 생략이 되고 안되고가 중요한 게 아니다.

 

에러 예제

class CastingTest1 {
	public static void main(String args[]) {
		Car car = new Car();
		FireEngine fe = (FireEngine)c; //형변환 에러
		fe.water();
	}
}

class Car {
	String color;
	int door;

	void drive() { 		// 운전하는 기능
		System.out.println("drive, Brrrr~");
	}

	void stop() {		// 멈추는 기능	
		System.out.println("stop!!!");	
	}
}

class FireEngine extends Car {	// 소방차
	void water() {		// 물을 뿌리는 기능
		System.out.println("water!!!");
	}
}

컴파일 에러는 나지 않는다.

실행시 `ClassCastException`이 발생한다.

 

 왜일까

실제 객체는 `Car`다. 즉 멤버가 4개다.

근데 `FireEngine`은 5개다. 실제 객체의 멤버 수를 넘을 수 없다.

→ 실제 객체인 `Car`에 `water()`가 존재하지 않는다.

 

 왜 컴파일 단계에서 에러가 나지 않는가

컴파일러는 형변환 연산자만 써주면 타입만 맞다면 실제 객체가 `Car`인지 아닌지 알 수 없다.

그래서 컴파일은 정상적으로 되나 실행하면 에러가 터지는 것.

 

 

instanceof 연산자

  • 참조변수의 형변환 가능여부 확인에 사용.
  • 가능하면 true반환
public class InstanceofTest {
    public static void main(String args[]) {
        FireEngine2 fe = new FireEngine2();
        Car2 car = new Car2();

        if(fe instanceof FireEngine2) {
            System.out.println("This is a FireEngine2 instance.");
        }

        if(fe instanceof Car2) {
            System.out.println("This is a Car2 instance.");
        }

        if(fe instanceof Object) {
            System.out.println("This is an Object instance.");
        }

        if(car instanceof FireEngine2 == false){
            System.out.println("불가능");
        }

        System.out.println(fe.getClass().getName()); // 클래스의 이름을 출력
    }
} // class
class Car2 {}
class FireEngine2 extends Car2 {}

 참조변수의 형변환은 왜 하는가

→ 참조변수(리모컨)을 변경함으로써 사용할 수 있는 멤버의 갯수를 조절하기 위해

다시 한번 말하지만 객체나 주소값이 바뀌지 않는다! 형만 바뀌는것이다.

 

 instanceof연산자는 언제 사용하나

→ 참조변수를 형변환하기 전에 형변환 가능여부를 확인할 때(일종의 방어코드로 이해했다.)