자손 instanceof
같 or 조상타입
✨조상타입
조상 = (조상타입) 자손;
조상타입
이어야함!!!!!!!!!💖💖티비 티는 스마트티비
💖💖💖인스턴스오브 조상타입
✨✨✨실제 가리키는 객체가 무엇인지 그림그려서 잘 확인하자!!
t
)로 자손 타입의 객체(SmartTv
)를 다루는 것Tv t = new SmartTv();
Tv
의 변수 5개, SmartTv
의 멤버 5+2=7개t
로 SmartTv
를 참조해도 멤버 7개 중 5개 밖에 사용하지 못한다. Car
- FireEngine
, Car
- Ambulance
끼리 형변환 가능(O) Car c = (Car)f;
① c
는 Car
타입, f
는 FireEngine
타입, 서로 다르므로, f
를 조상인 Car
타입으로 형변환 해서
② 참조변수 f
가 가리키는 객체의 주소(FireEngine
의 주소)를 참조변수 c
에 저장
③ c
도 FireEngine
을 가리키게 됨.
-> 그래도 c
가 다루는 ✨멤버는 4개
FireEngine f2 = (FireEngine)c;
FireEngine
타입으로 형변환c
가 가리키는 객체의 주소(FireEngine
의 주소)를 참조변수 f2
도 저장해 가리킴f2
가 다루는 멤버는 ✨다시 5개로 FireEngine f2 = (FireEngine)c;
-> 가 가능했던 건 ✨✨✨c
가 FireEngine
타입이기 때문이다.
-> 만약 ✨✨✨c
가 Car
타입이었다면 ClassCastException!!!!
(X) Ambulance a = (Ambulance)f;
: 상속관계가 아닌 클래스 간의 형변환 불가
class Car {
String color; // 멤버 4개
int door;
void drive() { // 운전하기
System.out.println("drive, brrr...");
}
void stop() { // 멈추기
System.out.println("stop!!!");
}
}
class FireEngine extends Car {
// 멤버 4+1 = 5개
void water() { // 물뿌리기
System.out.println("water~~~");
}
}
public class Ex7_07 {
public static void main(String[] args) {
// 다형성
// 그림1
Car car = null; // 참조변수car에 null로 초기화
FireEngine fe = new FireEngine(); //리모콘 5개
FireEngine fe2 = null;
fe.water();
// 그림2
car = (Car)fe; // (Car)생략 가능 -> 리모콘 4개
// car.water(); // car는 water()사용 불가능!!
fe2 = (FireEngine)car; // 생략 불가능 -> 리모콘 4개
fe2.water();
}
}
water~~~
water~~~
그림1
그림2
null
인지, 어떤 객체를 가리키는지 등등)✨ 잘 알아야 한다.✔ 다음은 에러
public class Ex7_07 {
public static void main(String[] args) {
Car car = new Car();
FireEngine fe = (FireEngine)car;
// -> 컴파일 ok이지만 형변환 실행 에러 java.lang.ClassCastException
fe.water(); // 컴파일 ok이지만
}
}
그림 잘못됐는데.... 형변환 가능하고, 저 객체 가리키는게 가능하다. 빨간 엑스 삭제!
이런 상태이기 때문에 ✨형변환은 가능한데 fe
가 ✨✨water()
를 호출을 못한다.
instanceof
연산자true
반환 instanceof
로 확인 해줘야 한다.참조변수a instanceof 타입B
: 참조변수a의 타입이 타입B로 형변환 가능한가?
: 참조변수a가 가리키는 객체가 타입B이냐? 또는 타입B의 자손이냐?
true
①참조변수a instanceof 타입A
: 타입이 자기자신으로 같으면
②참조변수a instatnceof 조상타입
false
: no, 그 외에 다!
자손참조변수 instanceof 자기자신타입 또는 조상타입
은 언제나 true!!Car c = new Car(); FireEngine f = new FireEngine(); boolean b = c instanceof FireEngine; System.out.println(b); //false c = (FireEngine)f; boolean o = c instanceof FireEngine; System.out.println(o); //true
void doWork(Car c) { if (c instanceof FireEngine) { //FireEngine이 매개변수와 같은타입 또는 조상타입이냐? FireEngine fe = (FireEngine)c; //true면 객체생성하고 그 참조변수fe에 매개변수의 객체주소를 넣어라. fe.water(); } }
이런 식으로 쓰인다는데.. 익숙해지자
doWork(Car c); doWork(new Car()); doWork(new FireEngine()); doWork(new Ambulance()); //Car 또는 Car의 모든 자손들 가능 //여기서 doWork(new FireEngine()); //객체생성 후 바로 넣기 //은 아래와 동일하다. Car c = new FireEngine(); //객체생성 후 참조변수를 만들어 받고 매개변수로 넣기 doWork(c);
Ch07Re
class Car{
String color;
int door;
void drive() {
System.out.println("drive: brr...");
}
void stop() {
System.out.println("stop!!!");
}
}
class FireEngine extends Car{
void water() {
System.out.println("water~~~");
}
}
class Am extends Car{
}
class Change{
static void doWork(Car cc) {
//Car와 그 자손들, 즉 Car c, FireEngine f, FireEngine ff 등 가능, 매개변수의 다형성!
if(cc instanceof FireEngine) { //cc의 타입이 FE 또는 FE의 자손이면 true
FireEngine fe = (FireEngine) cc; //매개변수로 들어온 주소를 왼쪽항에 저장
fe.water();
} else {
System.out.println("nope!");
}
}
}
public class Ex7_07 {
public static void main(String[] args) {
//water~~~
FireEngine f = new FireEngine();
Change.doWork(f); //가리키는 객체인 FE가 매개변수로 ->true
Car c = new FireEngine();
Change.doWork(c); //가리키는 객체인 FE가 매개변수로 ->true
Change.doWork(new FireEngine()); //타입 FE가 매개변수로 ->true
//nope!
Change.doWork(new Am()); //타입Am가 매개변수로 ->false
Change.doWork(new Car()); //타입Car가 매개변수로 ->false
Car cc = new Car();
FireEngine ff = new FireEngine();
boolean b = cc instanceof FireEngine; //cc의 타입이 Car->false
System.out.println(b);
//false여도 상속관계&&아래의 경우면 형변환 가능하다!
cc = (Car)ff;
// ff = (FireEngine) cc; 이건 안돼!!! ClassCastException
boolean o = cc instanceof FireEngine; //cc의 타입이 FE->true
System.out.println(o);
}
}
water~~~
water~~~
water~~~
nope!
nope!
public class Ex7_07 {
public static void main(String[] args) {
FireEngine fe = new FireEngine();
System.out.println(fe instanceof Object); // 조상이면 뭐든 true
System.out.println(fe instanceof Car);
System.out.println(fe instanceof FireEngine); // 자기자신도 true
fe.water();
//
Car car = new Car();
System.out.println(car instanceof Object);
System.out.println(car instanceof Car);
System.out.println(car instanceof FireEngine); // car의 타입 Car는 FireEngine 또는 FireEngine의 자손이 아니므로 false
fe.water();
//
car = (Car)fe; // 그러나 주소를 이렇게 바뀐다면?
// 즉 car는 FireEngine을 가리켜 주소값을 저장하게 된다. car의 타입은 FireEngine!
System.out.println(car instanceof Object);
System.out.println(car instanceof Car); // FE -- Car -> Car가 조상이므로 -> true
System.out.println(car instanceof FireEngine); // 자기자신을 가리키게 되므로 true
fe.water();
}
}
true
true
true
water~~~
true
true
false
water~~~
true
true
true
water~~~
아이구 어렵다. 복습하자.