class NormalA {
int num;
}
class NormalB {
int num;
}
public class Extends08_TypeCasting01 {
public static void main(String[] args) {
short s = 10;
int i = s; // 자동 형변환 (short -> int) : 작은용량에서 큰용량의 변수로
int j = 10;
// short k = j; // 에러(int -> short) : 큰 용량에서 작은 용량의 변수로
// 해결 방법은 강제 캐스팅 연산자를 앞에 붙여서 사용
short k = (short)j;
// 클래스의 레퍼런스 변수간의 형변환은 각 레퍼런스의 접근 범위에 영향을 받음
// 서로 다른 클래스 객체간의 형변환은 허용되지 않음
NormalA a1 = new NormalA();
/*
NormalB b1 = a1;
NormalB b1 = (NormalB)a1;
NormalB b1 = new NormalA();
모두 에러 */
NormalB b2 = new NormalB();
/*
NormalA a2 = b2;
NormalA a2 = (NormalA)b2;
NormalA a2 = new NormalB();
모두 에러 */
}
}
class SuperF {
int 부모멤버변수;
void abc() {System.out.println("부모메서드");}
}
class SubF extends SuperF {
int 자식멤버변수;
void abc() {System.out.println("자식메서드");}
}
public class Extends08_TypeCasting02 {
public static void main(String[] args) {
// 부모클래스의 객체 생성
SuperF super1 = new SuperF();
// 자식클래스의 객체 생성
SubF sub1 = new SubF();
// 1. 자식 클래스의 인스턴스 주소값을 부모클래스의 레퍼런스변수에 저장이 가능
// 부모참조변수 <- 자식 인스턴스의 주소 OK
super1 = sub1;
super1 = new SubF();
// 2. 부모 클래스의 인스턴스 주소값을 자식클래스의 레퍼런스 변수에 저장하는것은 불가능
// 자식참조변수 <- 부모 인스턴스의 주소 NOT OK
super1 = new SuperF();
// sub1 = super1; // 에러
// sub1 = new SuperF(); // 에러
// 3. 부모 클래스의 레퍼런스 주소가 갖고 있던 주소를 자식클래스의 레퍼런스 변수에 그래도
// 저장하고 싶다면, 강제캐스팅 연산을 이용해서 저장은 가능
SuperF super2 = new SuperF();
// SubF sub3 = (SubF)super2; // 문법상 에러는 없지만 실행하면 생기는 런테임에러가 발생
// 결국 자식클래스의 레퍼런스 변수는 지밖에 모르기때문에 저장된 주소를 찾아갔을 때
// 그것이 자식클래스의인스턴스가 아니고 부로 클래스의 인스턴스면 런타임에러가 발생
// 그럼 SubF sub3 = (SubF)super2; 는 왜 문법에러가 없을까
// 부모레퍼런스 변수가 갖고 있던 주소값을 자식 레퍼런스에 넣을 수 있는 경우를 선별해야 하는데
// 현재의 부모 레퍼런스변수가 저장한 주소에 자식 인스턴스가 저장된 경우로 그 경우를 제한
SuperF super3 = new SubF(); // 부모레퍼런스변수에 자식 인스턴스 저장
SubF sub3 = (SubF)super3; // 부모레퍼런스값을 자식레퍼런스벼눗에 저장
// 자식 레퍼런스 <- (타입캐스팅) 부모레퍼런스 <- 자식 인스턴스의 주소
// 자식 레퍼런스 <- (타입캐스팅) 부모레퍼런스 <- 부모 인스턴스의 주소 - 러타임에러
short a = 10;
int b = a;
a = (short)b;
// 4. 강제 캐스팅을 사용한 형변환 시 에러를 방지하는 방법
// instanceof 연산자
//SuperF super5 = new SuperF(); // 실행결과 : 형변환 실패
SuperF super5 = new SubF();
// SubF클래스로의 형변환가능성을 true/false 로 판단
if( super5 instanceof SubF ) {
SubF sub5 = (SubF)super5;
System.out.println("형변환 성공~!");
} else {
System.out.println("형변환 실패~!");
}
// 5. 자식 인스턴스를 저장하고 있는 부모 레퍼런스는
// 부모가 상속해준 멤버변수에만 접근이 가능합니다.
SuperF super6 = new SubF();
super6.부모멤버변수 = 100; //O
// super6.자식멤버변수 = 100; //X
super6.abc();
// 다만 메서드가 오버라이딩 되었다면, 부모클래스의 레퍼런스로 실행한 메서드는
// 자식 클래스에서 오버라이딩 된 메서드가 우선 실행
}
}
class SuperG {}
class SubG1 extends SuperG {}
class SubG2 extends SuperG {}
class SubG3 extends SuperG {}
public class Extends08_TypeCasting03 {
public static void main(String[] args) {
SuperG s = new SuperG();
SubG1 s1 = new SubG1();
SubG2 s2 = new SubG2();
SubG3 s3 = new SubG3();
if( s instanceof SubG1 )
System.out.println("SubG1 클래스 타입");
else if( s instanceof SubG2 )
System.out.println("SubG2 클래스 타입");
else if( s instanceof SubG3 )
System.out.println("SubG3 클래스 타입");
else if( s instanceof SuperG )
System.out.println("SuperG 클래스 타입");
// instanceof 연산자를 사용하여 부모와 자식클래스의 타입을 비교하는 경우
// 반드시 부모클래스는 마지막에 비교(자식이 먼저 위에서 부모로 판별될 수 있음)
if( s1 instanceof SubG1 )
System.out.println("SubG1 클래스 타입");
else if( s1 instanceof SuperG )
System.out.println("SuperG 클래스 타입");
}
}