참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 사용한다. 주로 조건문에 사용되며, instanceof의 왼족에는 참조변수를 오른쪽에는 타입(클래스명)이 피연산자로 위치한다. 그리고 연산의 결과로 boolean값인 true, false 중의 하나를 반환한다.
instanceof를 이용한 연산결과로 true를 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 뜻한다.
[참고] 값이 null인 참조변수에 대해 instanceof연산을 수행하면 false를 결과로 얻는다.
참조변수와 인스턴스의 연결
-메서드 : 조상클래스의 메서드를 자손의 클래스에서 오버라이딩 한 경우에도 참조변수의 타입에 관계없이 항상 실제 인스턴스의 메서드(오버라이딩된 메서드가 호출됨)
멤버변수의 경우 참조변수의 타입에 따라 달라짐
-멤버변수가 조상 클래스와 자손 클래스에 중복으로 정의된 경우,
조상 타입의 참조변수를 사용했을 때 조상 클래스에 선언된 멤버변수가 사용되고,
자손타입의 참조변수를 사용했을 때는 자손 클래스에 선언된 멤버변수가 사용된다.
예1)
예2)
예3)
instanceof를 이용한 연산결과로 true를 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 뜻한다.
[참고] 값이 null인 참조변수에 대해 instanceof연산을 수행하면 false를 결과로 얻는다.
void dowork(Car c){
if ( c instanceof FireEngine) {
FireEngine fe = (FireEngine)c;
fe.water();
}
else if( c instance of Ambulance) {
Ambulance a = (Ambulance)c;
a.siren();
}
. . . . . . .
}
if ( c instanceof FireEngine) {
FireEngine fe = (FireEngine)c;
fe.water();
}
else if( c instance of Ambulance) {
Ambulance a = (Ambulance)c;
a.siren();
}
. . . . . . .
}
참조변수와 인스턴스의 연결
-메서드 : 조상클래스의 메서드를 자손의 클래스에서 오버라이딩 한 경우에도 참조변수의 타입에 관계없이 항상 실제 인스턴스의 메서드(오버라이딩된 메서드가 호출됨)
멤버변수의 경우 참조변수의 타입에 따라 달라짐
-멤버변수가 조상 클래스와 자손 클래스에 중복으로 정의된 경우,
조상 타입의 참조변수를 사용했을 때 조상 클래스에 선언된 멤버변수가 사용되고,
자손타입의 참조변수를 사용했을 때는 자손 클래스에 선언된 멤버변수가 사용된다.
예1)
class Parent{
int x = 100;
void method() {
System.out.println("Parent Method");
}
}
class Child extends Parent {
int x = 200;
void method() {
System.out.println("Child Method");
}
}
Class BindingTest{
public static void main(String[] args) {
Parent p = new Child();
Child c = new Chile();
System.out.println("p.x = " + p.x);
p.method();
System.out.println("c.x = " + c.x);
c.method();
}
}
int x = 100;
void method() {
System.out.println("Parent Method");
}
}
class Child extends Parent {
int x = 200;
void method() {
System.out.println("Child Method");
}
}
Class BindingTest{
public static void main(String[] args) {
Parent p = new Child();
Child c = new Chile();
System.out.println("p.x = " + p.x);
p.method();
System.out.println("c.x = " + c.x);
c.method();
}
}
[결과값]
p.x = 100;
Chiild Method
c.x = 200;
Child Method
p.x = 100;
Chiild Method
c.x = 200;
Child Method
예2)
public class Parent {
public int su = 10;
void pr(){
System.out.println(su);
}
}
public int su = 10;
void pr(){
System.out.println(su);
}
}
public class Child extends Parent {
public int su = 20;
void pr(){
System.out.println(su);
}
}
public int su = 20;
void pr(){
System.out.println(su);
}
}
public class TestParentChild {
public static void main(String[] args) {
System.out.println("*Parent p1 = new Parent() *");
Parent p1 = new Parent();
System.out.print("Parent의 pr(): su = "); p1.pr();
System.out.println("p1.su = " + p1.su);
System.out.println("\n *Child c1 = new Child() *");
System.out.println("*Parent p1 = new Parent() *");
Parent p1 = new Parent();
System.out.print("Parent의 pr(): su = "); p1.pr();
System.out.println("p1.su = " + p1.su);
System.out.println("\n *Child c1 = new Child() *");
Child c1 = new Child();
System.out.print("Child의 pr() : su = "); c1.pr();
System.out.println("c1.su= "+c1.su);
System.out.println("\n *Parent p2 = new Child() *");
Parent p2 = new Child();
System.out.print("Child의 pr(): su = "); p2.pr();
System.out.println("p2.su = " +p2.su);
}
}System.out.println("\n *Parent p2 = new Child() *");
Parent p2 = new Child();
System.out.print("Child의 pr(): su = "); p2.pr();
System.out.println("p2.su = " +p2.su);
}
[Console]
*Parent p1 = new Parent() *
Parent의 pr(): su = 10
p1.su = 10
*Child c1 = new Child() *
Child의 pr() : su = 20
c1.su= 20
*Parent p2 = new Child() *
Child의 pr(): su = 20
p2.su = 10
*Parent p1 = new Parent() *
Parent의 pr(): su = 10
p1.su = 10
*Child c1 = new Child() *
Child의 pr() : su = 20
c1.su= 20
*Parent p2 = new Child() *
Child의 pr(): su = 20
p2.su = 10
마지막 선언 Parent p2 = new Child() 를 보면,
p2.su의 값을 출력해 보면 Parent클래스의 멤버변수 su값이 출력된다.
(조상타입의 참조변수를 이용하여 Child()클래스를 접근했으므로 참조 변수는 Parent의 su이다.)
하지만 참조메소드는 현재 인스턴스가 접근하는 클래스(Child())의 멤버 메소드 이므로,
void pr(){
System.out.println(su);
}
함수의 su가 this.su를 생략하고 있다고 보면, Child의 멤버변수 su의 값이 출력된다.
p2.su의 값을 출력해 보면 Parent클래스의 멤버변수 su값이 출력된다.
(조상타입의 참조변수를 이용하여 Child()클래스를 접근했으므로 참조 변수는 Parent의 su이다.)
하지만 참조메소드는 현재 인스턴스가 접근하는 클래스(Child())의 멤버 메소드 이므로,
void pr(){
System.out.println(su);
}
함수의 su가 this.su를 생략하고 있다고 보면, Child의 멤버변수 su의 값이 출력된다.
예3)
public interface Drawable {
public int PLAIN_PEN = 1;
public int BOLD_PEN = 2;
public int ITALIC_PEN = 3;
public void draw();
public void move(int x, int y);
}
public int PLAIN_PEN = 1;
public int BOLD_PEN = 2;
public int ITALIC_PEN = 3;
public void draw();
public void move(int x, int y);
}
public class Shape1 {
protected int x = 0;
protected int y = 0;
public Shape1() {
this(0,0);
}
public Shape1(int x, int y) {
this.x = x;
this.y = y;
}
}
protected int x = 0;
protected int y = 0;
public Shape1() {
this(0,0);
}
public Shape1(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Circle1 extends Shape1 implements Drawable {
protected int radius;
public Circle1(int x, int y, int radius) {
super(x, y);
this.radius = radius;
}
@Override
public void draw() {
System.out.println("x = " + x + ", y = " + y + " radius = "+radius);
}
@Override
public void move(int x, int y) {
System.out.println("x = " + (this.x + x) + ", y = " + (this.y+y) + " radius = "+ radius);
}
}
protected int radius;
public Circle1(int x, int y, int radius) {
super(x, y);
this.radius = radius;
}
@Override
public void draw() {
System.out.println("x = " + x + ", y = " + y + " radius = "+radius);
}
@Override
public void move(int x, int y) {
System.out.println("x = " + (this.x + x) + ", y = " + (this.y+y) + " radius = "+ radius);
}
}
public class Rectangle1 extends Shape1 implements Drawable {
protected int width;
protected int height;
public Rectangle1(int x, int y, int width, int height) {
super(x, y);
this.width = width;
this.height = height;
}
@Override
public void draw() {
System.out.println("x = " + x + ", y = " + y + " width = "+ width + ", height = " + height);
}
@Override
public void move(int x, int y) {
System.out.println("x = " + (this.x + x) + ", y = " + (this.y+y) + " width = "+ width + ", height = " + height);
}
}
protected int width;
protected int height;
public Rectangle1(int x, int y, int width, int height) {
super(x, y);
this.width = width;
this.height = height;
}
@Override
public void draw() {
System.out.println("x = " + x + ", y = " + y + " width = "+ width + ", height = " + height);
}
@Override
public void move(int x, int y) {
System.out.println("x = " + (this.x + x) + ", y = " + (this.y+y) + " width = "+ width + ", height = " + height);
}
}
public class InterfaceTest {
public static void main(String args[]){
public static void main(String args[]){
Circle1 c = new Circle1(10,10,100);
Rectangle1 r = new Rectangle1(20,20,50,50);
c.draw();
c.move(5, 5);
r.draw();
r.move(5, 10);
Rectangle1 r = new Rectangle1(20,20,50,50);
c.draw();
c.move(5, 5);
r.draw();
r.move(5, 10);
}
}[Console] InterfaceTest.java
x = 10, y = 10 radius = 100
x = 15, y = 15 radius = 100
x = 20, y = 20 width = 50, height = 50
x = 25, y = 30 width = 50, height = 50
x = 10, y = 10 radius = 100
x = 15, y = 15 radius = 100
x = 20, y = 20 width = 50, height = 50
x = 25, y = 30 width = 50, height = 50
public class InterfaceTestEx {
public static void main(String args[])
{
public static void main(String args[])
{
Circle1 c = new Circle1(10,10,100);
Shape1 s = new Circle1(20,20,200);
Drawable d = new Circle1(30, 30, 300);
c.draw();
//s.draw(); //The method draw()is undefined for the type Shape1
d.draw();
System.out.println("x = " + c.x + ", y = " + c.y);
System.out.println("x = " + s.x + ", y = " + s.y);
// System.out.println("x = " + d.x + ", y = " + d.y);
Shape1 s = new Circle1(20,20,200);
Drawable d = new Circle1(30, 30, 300);
c.draw();
//s.draw(); //The method draw()is undefined for the type Shape1
d.draw();
System.out.println("x = " + c.x + ", y = " + c.y);
System.out.println("x = " + s.x + ", y = " + s.y);
// System.out.println("x = " + d.x + ", y = " + d.y);
// Multiple makers at this line
// -x cannot be resolved or is not a fild
// -y cannot be resolved or is not a file
}
// -x cannot be resolved or is not a fild
// -y cannot be resolved or is not a file
}
}
[Console] InterfaceTestEx.java
x = 10, y = 10 radius = 100
x = 30, y = 30 radius = 300
x = 10, y = 10
x = 20, y = 20
x = 10, y = 10 radius = 100
x = 30, y = 30 radius = 300
x = 10, y = 10
x = 20, y = 20
InterfaceTestEx.java 부분을 살펴보자
s.draw();는 error가 뜬다. 이유는, 참조변수 Shape1으로 선언한 s 객체는 Shape1이 draw() 함수를 갖고 있지 않기 때문에
//The method draw()is undefined for the type Shape1 이라는 메시지가 뜨며 에러라고 표시된다.
마찬가지로 System.out.println("x = " + d.x + ", y = " + d.y);도 error 메시지가 뜨게 되는데, Drawable 클래스는 x, y라는 멤버변수를 갖고 있지 않기때문에, "Multiple makers at this line -x cannot be resolved or is not a fild -y cannot be resolved or is not a file" 라는 메시지가 뜨면서 에러가 뜬다.
s.draw();는 error가 뜬다. 이유는, 참조변수 Shape1으로 선언한 s 객체는 Shape1이 draw() 함수를 갖고 있지 않기 때문에
//The method draw()is undefined for the type Shape1 이라는 메시지가 뜨며 에러라고 표시된다.
마찬가지로 System.out.println("x = " + d.x + ", y = " + d.y);도 error 메시지가 뜨게 되는데, Drawable 클래스는 x, y라는 멤버변수를 갖고 있지 않기때문에, "Multiple makers at this line -x cannot be resolved or is not a fild -y cannot be resolved or is not a file" 라는 메시지가 뜨면서 에러가 뜬다.
'Java' 카테고리의 다른 글
표현언어(Expression Language) (0) | 2011.01.27 |
---|---|
파일과 입출력 API (0) | 2011.01.11 |
java.util 패키지(유틸리티 API) (0) | 2011.01.11 |
static정리 (0) | 2011.01.06 |
추상클래스 / 인터페이스 (0) | 2011.01.06 |