자바 프로그래밍을 하다보면 자식생성자와 부모생성자의 변수 혹은 메서드의 이름이 같은 경우 구분을 해줘야한다. 그럴 때 this와 super를 사용한다.
this와 this() 그리고, super와 super()는 맥락은 같지만 조금씩 쓰임새는 다르다.
this() -> this 메소드는 생성자 첫 문장에서만 사용 가능하다. 같은 클래스 내부의 다른 생성자를 호출할 때 사용한다.
this -> this 키워드는 인스턴스 자신을 가리키는 참조변수이다. 인스턴스의 주소가 저장되어, 숨겨진 채로 존재한다. static 메소드에서는 사용이 불가능하다. 왜냐하면 this 키워드는 인스턴스에서 사용이 가능한데 static 키워드는 객체를 생성하지 않아도 사용이 가능하기 때문이다.
super() -> Object클래스를 제외하고 모든 클래스는 this()나 super()를 호출해줘야 한다. 상속받은 클래스에서 생성자가 없는 경우, 컴파일러가 자동으로 추가해주지만 생성자가 있는 경우에는 명시적으로 super()를 호출해줘야 한다.
super -> super 키워드는 자식 클래스에서 부모 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.
this
this 키워드는 현재 클래스의 인스턴스를 의미하는 참조변수이다. 인스턴스의 주소가 저장되어, 숨겨진 채로 존재한다. this 키워드는 인스턴스에서 사용이 가능한데 static 키워드는 객체를 생성하지 않아도 사용이 가능하기에 static 메소드에서는 사용할 수 없다.
즉, 현재 클래스의 멤버변수를 지정할 때 사용한다. (멤버변수는 메소드를 포함해서 말한다.)
리턴값으로 자기 자신의 참조값을 전달하고 싶을 때는 this 키워드를 이용함으로써 해결한다.
import java.util.ArrayList;
class MyQueue {
ArrayList list;
MyQueue() {
this.list = new ArrayList();
}
public boolean isEmpty() {
if(this.list.size()==0) return true;
return false;
}
public Integer pop() {
if(this.isEmpty()){ // -> 이부분! 궁금!
System.out.println("Queue is empty");
return null;
}
int data=(int)this.list.get(0);
this.list.remove(0);
return data;
}
}
Q. 인스턴스가 생성되지 않았는데 어떻게 this.isEmpty()가 가능한가요?
A. this는 클래스 내에서 메소드나 속성이 접근되는 대상 인스턴스를 가르키기 위해 사용되는데 this.isEmpty()같이 클래스를 인스턴스화 하지 않은 상태에서 this를 사용할 수 있는 이유는 메소드가 코드에 적혀있는 부분은 이것이 "정의"될 때이기 때문이다. 정의될 때 이 인스턴스는 존재하지 않아도 된다. (정확히는, 존재하지 않아야 한다) 해당 메소드가 호출될 때에는 인스턴스가 이미 만들어져 있기 때문에, this라는 변수가 해당 인스턴스를 가르킬 수 있는 것이다.
즉, 메소드를 정의할 때에는 인스턴스가 존재하지 않지만 메소드를 호출할 때에는 인스턴스가 존재하고, this라는 변수에 실제로 접근되는 순간은 메소드가 호출될 때이다.따라서 메소드 정의시에는 인스턴스가 없는 것이 맞으며 정의된 메소드를 호출할 때에 인스턴스를 통해서 호출하기 때문에 이 때에는 이미 생성된 인스턴스를 통해 메소드를 호출한다는 것이다.
this()
this 메소드는 현재 클래스에 정의된 생성자를 부를때 사용된다. 생성자 첫 줄에서만 사용 가능하다. 같은 클래스 내부의 다른 생성자를 호출할 때 사용한다.
super
super 키워드는 자식 클래스에서 부모 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.
자식 클래스에서 상속받은 부모 클래스의 멤버변수를 참조할때 사용한다.
인터페이스는 인터페이스명.super.할것; 이런식으로 사용된다.
super()
Object클래스를 제외하고 모든 클래스는 this()나 super()를 호출해줘야 한다. 자식 클래스가 부모 클래스의 멤버를 사용할 수 있기 때문에 부모의 멤버들이 먼저 초기화 되어 있어야 한다.
상속받은 클래스에서 생성자가 없는 경우, 컴파일러가 자동으로 자식 클래스의 생성자에 추가해주지만 생성자가 있는 경우에는 명시적으로 super()를 호출해줘야 한다.
자식 생성자 안에서 부모 클래스의 생성자를 호출할 때 사용한다.
사용 예시
public class Test {
public static void main(String[] args) {
B1 b1 = new B1();
}
}
class A1 {
public int a1;
public A1 () {
this(1);
System.out.println("인자가 없는 A 생성자");
}
public A1 (int a1) {
this.a1=a1;
System.out.println("인자가 1개인 A 생성자");
}
public A1 testMethod(){
return this; // 자기자신 리턴
}
}
class B1 extends A1 {
public B1 () {
super();
System.out.println("인자가 없는 B 생성자");
}
}
- B1 객체 생성시 호출 순서
- B1() 생성자 호출
- super()에 의하여, A1() 생성자 호출
- this(1)에 의하여, A1(int) 생성자 호출
- B1 객체 생성 완료