this
this는 현재 클래스의 인스턴스, 지금 실행상태에 있는 인스턴스의 특정 필드를 지정할 때 사용한다.
class Test{
int age;
public void setAge(int age){
this.age = age;
}
}
다른객체에서 Test test = new Test();
test.setAge(20);
이라고 하면 위에있는 setAge(int age);가 작동한다.
setAge(int age); 메소드를 보면 파라미터로 전달된 int의 이름인 age와 Test 클래스의 필드값이 age가
같은 이름이기 때문이다.
this.age는 '이 age는 지금 메소드(setAge)의 파라미터인 age 값이 아니라 클래스의 필드인 age다' 라는 것을
의미한다.
그리고 문장이 메소드안에 존재하더라도 age는 클래스의 필드임을 확실히 해두기 위해서도 사용한다.
this는 인스턴스가 만들어지기 전에 이미 시작을 하기 때문에 static한것에서는 사용할 수 없다.
this();
생성자를 부르기 위해서 사용된다.
class Person{
int age;
String name;
String address;
public Person(){
this(0, null, null);
}
public Person(int age){
this(age, null, null);
}
public Person(int age, String name){
this(age, name, null);
}
public Person(int age, String name, String address){
this.age = age;
this.name = name;
this.address = address;
}
}
한 사람에 대한 나이, 이름, 주소를 저장하는 클래스인데 생성자를 살펴보면 점차 파라미터(넘겨받는 값)이 늘어난다.
다른 클래스에서
1. Person jane = new Person(23, "jane", "America");
2. Person jane = new Person(23, "jane");
3. Person jane = new Person(23);
4. Person jane = new Person();
위와 같이 다양한 방법으로 인스턴스를 생성할 수 있도록 여러종류의 생성자를 마련했을 때 this();가 유용하게
쓰일 수 있다.
생성자끼리도 서로가 서로를 호출 할 수 있는(객체지향에서는 메시지를 전달) 방법이 this()를 활용하는 것이다.
2,3,4번 모두 첫번째를 호출해서 인스턴스를 만들게 된다.
super
super는 자식클래스가 부모 클래스로부터 상속받은 멤버를 참조할 때 사용한느 참조 변수이다.
클래스 내의 멤버변수와 지역변수의 이름이 같을 경우 구분을 위해 this를 사용하듯이 부모클래스와 자식클래스의
멤버 이름이 같은 경우 super를 사용한다.
this와 super는 인스턴스의 주소값을 저장하는데 static메소드(클래스메소드)와는 무관하게 사용된다.
class JavaApp {
public static void main(String[] args) {
Child child = new Child();
child.childMethod();
}
}
class Parent {
int x = 10;
}
class Child extends Parent {
int x = 20;
void childMethod() {
System.out.println("x=" + x);
System.out.println("this.x=" + this.x);
System.out.println("super.x=" + super.x);
}
}
위 예제 실행 시 다음의 결과가 출력된다.
x=20
this.x=20
super.x=10
super()
super()는 부모클래스의 생성자를 호출하는 메소드이다. 상속받은 자식 클래스가 부모클래스의 멤버를 사용할 경우가
있을수도 있으므로 부모클래스를 우선적으로 초기화해줘야 한다. 부모클래스의 생성자는 자식 클래스의 생성자
첫줄에서 호출해준다. 이러한 부모클래스에 대한 생성자 호출은 상속관계에 따라 Object클래스까지 올라가서
마무리된다.
Object클래스를 제외한 모든 클래스의 생성자의 첫줄에는 반드시 자신의 클래스의 또다른 생성자, this() 또는
부모클래스의 생성자, super()를 호출해줘야 한다.
이렇게 하지 않으면 컴파일러가 자동으로 super()를 생성자의 첫줄에 호출한다.
class JavaApp {
public static void main(String[] args) {
Point3D point3d = new Point3D(); //Point3D() 생성자로 초기화 및 인스턴스 생성
System.out.println("point3d.x=" + point3d.x);
System.out.println("point3d.y=" + point3d.y);
System.out.println("point3d.z=" + point3d.z);
}
}
class Point {
int x = 10;
int y = 20;
Point(int x, int y) {
//생성자의 첫줄에 다른 생성자를 호출하지 않았기 때문에,
//컴파일러가 이 부분에 super()를 호출한다.
//부모클래스이므로 Object 클래스의 super()가 호출된다.
this.x=x;
this.y=y;
}
}
class Point3D extends Point {
int z = 30;
Point3D() {
this(100, 200, 300); //자신의 클래스의 또다른 생성자 호출
}
Point3D(int x, int y, int z) {
super(x, y); //부모클래스 생성자 호출
this.z = z;
}
}
위 예제 실행시 다음의 결과가 출력된다.
point3d.x=100
point3d.y=200
point3d.z=300
this와 super를 여러개 사용하고 싶으면 생성자에서 일반 메소드를 호출하도록 만들어주면 된다.
중복적인 로직을 가지는 코드 구문이 나온다면 메소드화 시켜 호출해서 사용하도록 만들어 준다.
this나 super를 사용하는 이유중에서는 동일한것을 호출해서 사용하고 싶었기 때문에 사용하는 것이다.
두개를 같이 처리하고 싶은 경우에 같이 적을 수 없기 때문에 일반 메소드를 만들어서 그것을 생성자에서 호출하도록
만들어 주는것이다.
기초클래스가 갖고있는 동일한 변수값을 갖고오고 싶으면 super를 사용하면 된다.
기초클래스는 서브클래스가 몇개가 있던 상관없지만 기초클래스가 서브클래스에서 가져올 수는 없다.
갖고 있는것을 가져올때는 this를 사용하면 되고 기초클래스에서 가져오고 싶을때는 super를 사용하면 된다.
생략이 되어 있다면 그것은 무조건 this라고 생각하면 된다.
기초클래스에도 있고 서브클래스에도 있는건 중복된 것이 아닌 overriding이다
서브클래스는 기초클래스를 상속받기 때문에 서브클래스에 없고 기초클래스에 있는 것은 this를 붙여서 사용할수 있다.
외부에서는 getter, setter를 이용하지만 서브클래스에서는 그냥 사용 할 수 있게 하고 싶다면
protected로, 서브클래스에서도 getter, setter 이용해서 사용하게 하고 싶으면 private으로 해주면 된다.
동일한 패키지 내에서는 인스턴스를 이용해 접근이 가능하다.
기초클래스에서 private으로 되어있다면 getter, setter로 가져와야 하는데 출력문에서 get000()으로 사용하면
출력이 가능하다.
이것은 this.get000()과 같은것이다.
굳이 super라고 쓰지 않은것은 private일 때는 super를 붙여봤자 안되기 때문이다.