프로그래밍 언어/자바의 정석 기초편

자바의 정석 기초편 ch7-24,25 참조변수의 형변환(2)

life grow 2022. 9. 3. 18:04

car.door,

car.color는 되지만

car.water()는 안된다. < Car 클래스 멤버에 없기 때문에

 

public class Carto {
	public static void main(String[] args) {
		Car car = null;
		FireEngine fe = new FireEngine();
		FireEngine fe2 = null;
		
		fe.water();
		car = (Car)fe;  // car = (Car)fe;에서 형변환이 생략됨
//		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!!!");
	}
}

 

많이 받는 질문들

 

Car car = null;
FireEngine fe = null;

둘 다 null이라 객체가 없는데 형변환에는 아무런 문제가 없다.

근데 실행하면 NullPointerException에러가 난다.

왜냐하면 아무객체가 없으니까 에러가 난다.

 

형변환할 때 중요한 게 실제 인스턴스가 뭔지가 중요하다.

실제 객체의 멤버가 5개니까 5개보다 크면 안 된다.

5개가 기준이 된다.

 

형변환은 조상, 자손 관계면 무조건 된다.

그렇기 때문에 문법상에는 문제가 없지만, 실제 실행했을 때 문제가 없으려면

참조변수의 멤버를 5개 안으로 줄였다가, 넓혔다가 하는 건 괜찮다.

근데 5개 이상으로 늘리면 안 된다. 5개만 안 넘으면 된다!

 

형변환이 되냐, 안되냐로 따지는 건 별로 의미가 없다.

참조변수의 타입만 따질 게 아니라, 참조변수들이 가리키는

실제 인스턴스가 뭔지를 확인하고 그 멤버의 개수를 넘어서면 안 된다.

참조변수간의 형변환이 중요한 게 아니라 실제 가리키는 객체가 뭔지가 중요하다.

 

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

그래서 통과가 된다.

 

Car c = new Car();

FireEngine fe = (FireEngine)c;

fe가 가리키는 객체에 water()를 호출했는데 water()가 없다.

객체가 Car 인스턴스니까

컴파일 에러는 아니고 실행하면 형변환 실행 에러가 나온다.

 

근데 컴파일러는 속는다. 형변환 타입만 맞으면 컴파일러는 ok

컴파일러가 실제 실행했을 때 어떻게 되는지 다 확인을 못하니까

 

c와 fe가 조상과 자손의 관계니까 형변환은 가능하지만

실제 인스턴스가 Car인스턴스이기 때문에 멤버 4개를 넘어서면 안 된다.

Car인스턴스의 멤버는 4개니까

FireEngine타입 fe는 멤버가 5개이다.