📌 학습 목차
24-1. 참조 변수의 형변환
24-2. 참조 변수의 형변환 예제
24-1. 참조 변수의 형변환
참조 변수의 형변환: 참조 변수 타입을 변경해 사용할 수 있는 객체의 멤버 개수를 조절하는 것
•참조 변수의 형변환은 사용할 수 있는 객체의 멤버 개수를 조절하기 위해 참조 변수의 종류를 바꾸는 것으로
값이 변경되는 기본형의 형변환처럼 참조 변수에 저장된 객체의 주솟값이 변환되는 것이 아님
•참조 변수의 형변환은 서로 상속 관계에 있는 클래스 사이에서만 가능함
이에 조상 타입과 자손 타입 간의 형변환은 가능하나, 상속 관계가 아닌 자손 타입 간의 형변환은 허용되지 않음
•참조 변수의 형변환은 조상의 조상으로도 형변환이 가능하므로, 모든 참조 변수는 Object 타입으로 형변환될 수 있음
단, Object 타입의 참조 변수는 Object 클래스에 정의된 멤버만 다룰 수 있음
•자손 타입에서 조상 타입으로 참조 변수 형변환을 하는 up-casting의 경우,
참조 변수가 다룰 수 있는 객체의 멤버 개수가 감소하는 안전한 형변환에 해당하므로 형변환을 생략할 수 있음
반면 조상 타입에서 자손 타입으로 참조 변수 형변환을 하는 down-casting의 경우,
참조 변수가 다룰 수 있는 객체의 멤버 개수가 증가하는 불안전한 형변환에 해당하므로 형변환을 생략할 수 없음
•참조 변수의 형변환 시 참조 변수가 참조하는 실제 객체 타입이 무엇인지 먼저 확인한 후,
해당 객체의 멤버 개수를 넘지 않도록 조절하는 것이 중요함
package chap_07;
// 1) 조상 클래스
class Phone6 {
String name;
String type;
int capacity;
int price;
}
// 2-1) 자손 클래스
class UpgradedPhone7 extends Phone6 {
void useStandBy() {}
void useNameDrop() {}
}
// 2-2) 자손 클래스
class UpgradedPhone8 extends Phone6 {
void useStandBy() {}
void useNameDrop() {}
}
public class _24_Example1 {
public static void main(String[] args) {
📌 // 3-1) 자손 타입의 참조 변수로 같은 타입의 객체를 참조할 경우
UpgradedPhone7 u1 = new UpgradedPhone7();
System.out.println(u1.name);
System.out.println(u1.type);
System.out.println(u1.capacity);
System.out.println(u1.price);
u1.useStandBy();
u1.useNameDrop();
📌 // 3-2) 자손 타입의 참조 변수를 조상 타입의 참조 변수로 형변환할 경우
Phone6 p = u1; // Phone6 p = (Phone6)u1;
System.out.println(p.name);
System.out.println(p.type);
System.out.println(p.capacity);
System.out.println(p.price);
// p.useStandBy(); -> 에러 발생
// p.useNameDrop(); -> 에러 발생
📌 // 3-3) 조상 타입의 참조 변수를 자손 타입의 참조 변수로 형변환할 경우
UpgradedPhone7 u2 = (UpgradedPhone7)p;
System.out.println(u2.name);
System.out.println(u2.type);
System.out.println(u2.capacity);
System.out.println(u2.price);
u2.useStandBy();
u2.useNameDrop();
📌 // 3-4) 자손 타입의 참조 변수를 다른 자손 타입의 참조 변수로 형변환할 경우
// UpgradedPhone8 u3 = (UpgradedPhone8)u1; -> 에러 발생
}
}
3-1) 자손 타입의 참조 변수로 같은 타입의 객체를 참조할 경우
•Phone6 클래스와 UpgradedPhone7 클래스가 서로 상속 관계에 있을 때
자손인 UpgradedPhone7 타입의 참조 변수 u1으로 같은 타입의 UpgradedPhone7 인스턴스를 참조할 경우,
인스턴스의 모든 멤버를 사용할 수 있음
즉, 6개(name, type, capacity, price, useStandBy(), useNameDrop())의 멤버를 다룰 수 있는 참조 변수 u1은
Phone6 클래스로부터 상속받은 멤버 4개(name, type, capacity, price)와
UpgradedPhone7 클래스에서 추가된 멤버 2개(useStandBy(), useNameDrop())를 포함해
총 6개의 UpgradedPhone7 인스턴스 멤버를 모두 사용할 수 있음
3-2) 자손 타입의 참조 변수를 조상 타입의 참조 변수로 형변환할 경우
•자손인 UpgradedPhone7 타입의 참조 변수 u1을 조상인 Phone6 타입의 참조 변수 p로 형변환할 경우,
참조 변수 u1에 저장된 UpgradedPhone7 인스턴스 주솟값이 참조 변수 p에 저장되어 참조 변수 p로 인스턴스를 다룰 수 있게 됨
•조상인 Phone6 타입의 참조 변수 p로 자손 타입의 UpgradedPhone7 인스턴스를 참조할 경우, 인스턴스 멤버 중 4개만 사용할 수 있음
즉, 4개(name, type, capacity, price)의 멤버를 다룰 수 있는 참조 변수 p는
UpgradedPhone7 인스턴스 멤버 중 Phone6 클래스에 정의된 멤버 4개(name, type, capacity, price)만 사용할 수 있음
•참조 변수가 다룰 수 있는 인스턴스 멤버 개수가 6개(u1)에서 4개(p)로 감소하는 up-casting의 경우,
안전한 형변환에 해당하므로 형변환을 생략할 수 있음
3-3) 조상 타입의 참조 변수를 자손 타입의 참조 변수로 형변환할 경우
•조상인 Phone6 타입의 참조 변수 p를 자손인 UpgradedPhone7 타입의 참조 변수 u2로 형변환할 경우,
참조 변수 p에 저장된 UpgradedPhone7 인스턴스 주솟값이 참조 변수인 u2에 저장되어 참조 변수 u2로 인스턴스를 다룰 수 있게 됨
•자손인 UpgradedPhone7 타입의 참조 변수 u2로 같은 타입의 UpgradedPhone7 인스턴스를 참조할 경우,
3-1)과 같이 인스턴스의 모든 멤버를 사용할 수 있음
•참조 변수가 다룰 수 있는 인스턴스 멤버 개수가 4개(p)에서 6개(u2)로 증가하는 down-casting의 경우,
불안전한 형변환에 해당하므로 형변환을 생략할 수 없음
3-4) 자손 타입의 참조 변수를 다른 자손 타입의 참조 변수로 형변환할 경우
•서로 상속 관계에 있지 않는 UpgradedPhone7 클래스와 UpgradedPhone8 클래스 간의 참조 변수 형변환은 허용되지 않음
24-2. 참조 변수의 형변환 예제
package chap_07;
// 1) 조상 클래스
class Phone7 {
String name;
String type;
int capacity;
int price;
}
// 2) 자손 클래스
class UpgradedPhone9 extends Phone7 {
void useStandBy() {}
void useNameDrop() {}
}
public class _24_Example2 {
public static void main(String[] args) {
📌 // 3) 참조 변수 및 객체 생성
Phone7 p = null;
UpgradedPhone9 u1 = new UpgradedPhone9();
UpgradedPhone9 u2 = null;
📌 // 4-1) 자손 타입의 참조 변수로 같은 타입의 객체 멤버를 호출할 경우
u1.useStandBy();
📌 // 4-2) 자손 타입의 참조 변수를 조상 타입의 참조 변수로 형변환할 경우
p = u1; // p = (Phone7)u1;
📌 // 4-3) 조상 타입의 참조 변수로 자손 타입의 객체 멤버를 호출할 경우
// p.useStandBy(); -> 에러 발생
📌 // 4-4) 조상 타입의 참조 변수를 자손 타입의 참조 변수로 형변환할 경우
u2 = (UpgradedPhone9)p;
📌 // 4-5) 자손 타입의 참조 변수로 같은 타입의 객체 멤버를 호출할 경우
u2.useStandBy();
}
}
3) 참조 변수 및 객체 생성 / 4-1) 자손 타입의 참조 변수로 같은 타입의 객체 멤버를 호출할 경우
•Phone7 클래스와 UpgradedPhone9 클래스가 서로 상속 관계에 있을 때
조상인 Phone7 타입의 참조 변수 p와 자손인 UpgradedPhone9 타입의 참조 변수 u2가 생성된 후, 대입 연산자에 의해 null이 저장됨
•자손인 UpgradedPhone9 타입의 참조 변수 u1이 생성된 후, new 연산자에 의해 같은 타입의 UpgradedPhone9 인스턴스가 생성됨
이때 대입 연산자에 의해 UpgradedPhone9 인스턴스 주솟값이 참조 변수 u1에 저장되어
참조 변수 u1으로 UpgradedPhone9 인스턴스 멤버에 접근할 수 있게 됨
•자손인 UpgradedPhone9 타입의 참조 변수 u1으로 같은 타입의 UpgradedPhone9 인스턴스를 참조할 경우,
인스턴스의 모든 멤버를 사용할 수 있음에 따라 useStandBy 메서드를 호출할 수 있음
4-2) 자손 타입의 참조 변수를 조상 타입의 참조 변수로 형변환할 경우
•자손인 UpgradedPhone9 타입의 참조 변수 u1을 조상인 Phone7 타입의 참조 변수 p로 형변환할 경우,
참조 변수 u1에 저장된 UpgradedPhone9 인스턴스 주솟값이 참조 변수 p에 저장되어 참조 변수 p로 인스턴스를 다룰 수 있게 됨
•조상인 Phone7 타입의 참조 변수 p로 자손 타입의 UpgradedPhone9 인스턴스를 참조할 경우,
인스턴스 멤버 중 Phone7 클래스에 정의된 멤버 4개(name, type, capacity, price)만 사용할 수 있음
•참조 변수가 다룰 수 있는 인스턴스 멤버 개수가 6개(u1)에서 4개(p)로 감소하는 up-casting의 경우,
안전한 형변환에 해당하므로 형변환을 생략할 수 있음
4-3) 조상 타입의 참조 변수로 자손 타입의 객체 멤버를 호출할 경우
•조상인 Phone7 타입의 참조 변수 p는 UpgradedPhone9 인스턴스의 멤버 중
Phone7 클래스에 정의된 멤버 4개(name, type, capacity, price)만 사용할 수 있음에 따라 useStandBy 메서드를 호출할 수 없음
4-4) 조상 타입의 참조 변수를 자손 타입의 참조 변수로 형변환할 경우
•조상인 Phone7 타입의 참조 변수 p를 자손인 UpgradedPhone9 타입의 참조 변수 u2로 형변환할 경우,
참조 변수 p에 저장된 UpgradedPhone9 인스턴스 주솟값이 참조 변수 u2에 저장되어 참조 변수 u2로 인스턴스를 다룰 수 있게 됨
•자손인 UpgradedPhone9 타입의 참조 변수 u2로 같은 타입의 UpgradedPhone9 인스턴스를 참조할 경우,
인스턴스의 모든 멤버를 사용할 수 있음
•참조 변수가 다룰 수 있는 인스턴스 멤버 개수가 4개(p)에서 6개(u2)로 증가하는 down-casting의 경우,
불안전한 형변환에 해당하므로 형변환을 생략할 수 없음
4-5) 자손 타입의 참조 변수로 같은 타입의 객체 멤버를 호출할 경우
•자손인 UpgradedPhone9 타입의 참조 변수 u2로 같은 타입의 UpgradedPhone9 인스턴스를 참조할 경우,
인스턴스의 모든 멤버를 사용할 수 있음에 따라 useStandBy 메서드를 호출할 수 있음
Reference
[남궁성의 정석코딩] Java의 정석 기초편 강의
[도우출판] Java의 정석 기초편 / 기본편