this참조
자바에서 클래스를 정의하고 객체를 생성하여 사용할 때를 그림으로 표현하면 다음과 같다.
앞의 예제에 따라 만들어진 Point객체 3개
메모리에 만들어진 형태를 그려보면 다음과 같은 형태이다.
위 그림으로 이해할 수 있는 것은 객체를 생성하면 GC를 통해 heap메모리에 객체가 생성되고
참조변수를 통해 생성된 객체를 참조하는 형태가 만들어진다.
그리고 참조변수를 통해 생성된 객체의 멤버에 접근하여 해당 객체의 속성이나 기능을 사용
위 그림처럼 객체가 하나가 아니라 여러 개라면?
멤버 변수는 객체의 개수만큼 각각 생성된다.
앞에서 객체를 이해하기 위해 필드와 메서드를 객체 안에 다 묶어서 표현했지만
사실 메서드는 객체가 생성될 때마다 메모리에 만들어지지 않는다.
위 그림과 같이 각각의 객체의 값은 별도로 존재하지만 메서드는 하나를 가지고 공유하는 형태이다.
그럼 객체가 여러 개 생성되도 멤버 메서드는 하나라는 의미를 받아 들이고 다음과 같이 생각해본다.
printPoint()메서드는 x와 y의 값이 여러 개 인데 어떻게 각 객체가 가진 x, y값을 찾아 출력할 수 있을까?
다음 예제를 이해해본다.
class Point {
int x;
int y;
void pointPrint(Point tmp) {
System.out.println("[" + tmp.x + "," + tmp.y + "]");
}
Point() {
} // 디폴트 생성자
Point(int a) {
x = a;
y = a;
}
Point(int a, int b) {
x = a;
y = b;
}
}
public class Exam {
public static void main(String[] args) {
Point point1 = new Point();
Point point2 = new Point(10);
Point point3 = new Point(20, 30);
point1.pointPrint(point1);
point2.pointPrint(point2);
point3.pointPrint(point3);
}
}
원래 예제의 pointPrint()메서드를 수정하고 그에 맞게 호출해 보았다.
전달받은 Point객체의 x, y값을 출력하도록 변경한 것이다.
실행결과는 Point를 전달하지 않던 방법과 동일하다.
위 내용을 다음과 같이 수정해 본다.
class Point {
int x;
int y;
void pointPrint() { //이 부분 수정
System.out.println("[" + this.x + "," + this.y + "]");
}
Point() {
} // 디폴트 생성자
Point(int a) {
x = a;
y = a;
}
Point(int a, int b) {
x = a;
y = b;
}
}
public class Exam {
public static void main(String[] args) {
Point point1 = new Point();
Point point2 = new Point(10);
Point point3 = new Point(20, 30);
point1.pointPrint();
point2.pointPrint();
point3.pointPrint();
}
}
pointPrint()메서드에 this를 명시해 보았다. 실행결과는 동일하다.
그럼 this는 무엇일까?
정의를 먼저 한다면
멤버 메서드를 호출한 객체를 참조하는 참조변수이다.
this의 동작은 다음과 같다.
생성자를 비롯해 멤버 메서드를 호출하면 자동으로 호출한 객체의 참조가 전달되며
멤버 메서드는 이를 받기 위해 매개변수로 this라는 참조변수가 생략된 형태로 존재한다.(직접사용 불가)
단 this를 명시하여 클래스 내부에서 사용하는 객체의 멤버를 이용할 수 있다.
static 메서드는 this가 없다.(static 멤버는 동일한 클래스의 객체 간에 공유하기 위한 멤버이다.)
다음 예제를 통해 이해하도록 한다.
class ThisTest {
int n;
void printN() { // printN(ThisTest this) this매개변수 생략
System.out.println("메서드를 호출한 객체 : " + this + "의 멤버 n값 : " + this.n);
}
}
public class Exam {
public static void main(String[] args) {
ThisTest ob1 = new ThisTest();
System.out.println("생성된 ob1객체 : " + ob1);
ThisTest ob2 = new ThisTest();
System.out.println("생성된 ob1객체 : " + ob2);
ob1.n = 10;
ob2.n = 20;
ob1.printN(); //printN(ob1); 객체 참조 생략
ob2.printN(); //printN(ob2); 객체 참조 생략
}
}
}
실행결과
위 예제를 보면 생략된 형태로 this가 존재한다는 것을 확인할 수 있으며
this를 활용하면 메서드를 호출한 객체를 구분할 수 있다.
this활용 예1.
매개변수 이름과 멤버변수 이름이 중복될 때 this를 이용하여 객체의 멤버를 명시
this를 활용하는 예제를 보자.
package exam;
class ThisTest {
int n;
ThisTest(int n) {
n = n;
}
void printN() {
System.out.println(n);
}
}
public class Exam {
public static void main(String[] args) {
ThisTest ob = new ThisTest(10);
ob.printN();
}
}
위 코드의 출력 결과는 0이다.
왜일까?
처음 그림에서 보듯 객체들은 하나의 함수를 객체들 간에 공유하는 형태이다.
그렇다면 객체가 멤버 메서드를 호출 할 때
호출되는 메서드에게 어떤 객체의 값을 사용하는지 객체를 알려줄 필요가 있다.
위 예제에서 ThisTest 객체를 생성할 생성자에 매개변수 이름이 n이다.
그리고 멤버변수의 이름도 n이다.
따라서 메서드 지역에 해당 이름이 있기 때문에 멤버변수 n으로 인식할 수 없다.
이를 this를 명시하여 구분해 줄 수 있다.
package exam;
class ThisTest {
int n;
ThisTest(int n) {
this.n = n; // n = n;
}
void printN() {
System.out.println(this.n);
}
}
public class Exam {
public static void main(String[] args) {
ThisTest ob = new ThisTest(10);
ob.printN();
}
}
this활용 예2.
생성자를 재사용할 때 this()형태로 다른 생성자를 이용할 수 있다.
package exam;
class ThisTest {
int n;
ThisTest() {
this(10); // int를 받는 다른 생성자 호출
System.out.println("디폴트 생성자");
}
ThisTest(int n) {
this.n = n; // n = n;
System.out.println("int 받는 생성자");
}
void printN() {
System.out.println(this.n);
}
}
public class Exam {
public static void main(String[] args) {
ThisTest ob = new ThisTest();
ob.printN();
}
}
위 예제는 객체를 생성할 때 디폴트 생성자를 호출했다.
디폴트 생성자가 호출되고 this(10)을 통해 다른 생성자를 호출한다.
ThisTeat(int n) 생성자가 동작된 후 디폴트 생성자 동작이 완료되는 순서로 동작한 것이다.
즉 생성자에서 다른 생성자를 호출할 필요가 있을 때 사용한다.(기존 생성자 재사용)
주의)
다른 생성자를 this()를 이용하여 마음껏 호출이 가능.
단, 생성자의 첫 번째 동작으로만 호출이 가능
'교육자료 > Java' 카테고리의 다른 글
Java 클래스 구성 요소(접근 제어자) (0) | 2017.06.18 |
---|---|
Java 객체 관리 Garbage Collection (0) | 2017.06.16 |
Java 클래스 구성요소(생성자) (0) | 2017.06.16 |
Java 클래스 구성요소(멤버필드와 멤버메서드) (0) | 2017.06.15 |
Java 클래스 (Class기초 문법과 OOP 개념) (0) | 2017.06.15 |