본문 바로가기

Java 문법 개념

참조변수 this 와 super / 생성자 this() 와 super() / 생성자 중요개념

참조변수 this

      • this 는 인스턴스 자신을 가리키는 일종의 참조변수이다.
         * this에는 인스턴스 본인의 주소값이 저장되어 있다.
      • 참조변수를 통해서 객체의 변수에 접근할 수 있다는 사실은 당연한 개념이다.
        마찬가지로, 참조변수 this 를 통해서도 객체의 변수에 접근할 수 있다.
          this . iv_이름
      • 클래스를 작성 할 때, 필드에 선언된 iv를 클래스 내부에서 사용할 때, 우리는 " iv_이름 " 만으로 그 값을 사용한다.
        하지만, 사실 컴파일러가 우리를 대신해서 몰래 " iv_이름 " 앞에 추가해주는 것이 있다. 
        바로 참조변수 this 가 컴파일러에 의해서 자동으로 추가 된다.
      • 즉, 원래는 iv 를 클래스 내부에서 사용할 때 마다, 항상 this.  를 변수 앞에 붙여야하지만, 이를 컴파일러가 자동으로 추가해주기 때문에 우리는 편리하게 this. 을 생략한 채로 iv 를 사용할 수 있었던 것이다.
      • 단, lv 와 iv의 이름이 같을 경우에는 이 둘을 구별하기 위해서 iv 앞에 참조변수 this 를 꼭 사용해야 한다.
        아래 코드를 보면 무슨 뜻인지 바로 이해 할 수 있다.
1
2
3
4
5
6
7
8
9
class person {
    static int age; // iv의 이름이 age 이다.
    String name;
 
    person(int age, String name) { // lv의 이름 또한 age 이다.
        this.age = age; // iv와 lv를 구분해주기 위해서 iv 앞에 참조변수 this를 붙인다.
// age = age; ---> 불가능한 코드
        this.name = name;
    }
}
cs
  • 참조변수 this 는 인스턴스 메서드(생성자 포함)에서만 사용할 수 있다.
     * 참조변수 this 는 객체 자신을 가리키므로 인스턴스의 생성 없이도 호출이 가능해야하는 스태틱 메서드에서는 당연히 참조변수 this를 사용 할 수 없다.
  • 참조변수 this 는 스태틱 메서드에서는 사용할 수 없다.

 


 

생성자 this()

    • 생성자 this() 는 생성자 내부에서 다른 생성자를 호출할 때 사용한다.
    • 반드시, 생성자 내부에서 첫 줄 에서만 사용할 수 있다.
    아래의 코드를 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
class person {
    int age;
    String name;
 
    person() {
        this(1,"baby"); // person(int age, String name) 생성자를 호출한다.
    }
    person(int age, String name) {
        this.age = age;
        this.name = name;
    }
}
 
cs
  • 위의 코드에는 생성자가 2개가 있다.
  • person() 생성자 내부에 있는 this(1, "baby")person(int age, String name) 생성자를 호출한다.
  • this() 생성자는 생성자 내부에서 사용되었고, 내부 블럭의 첫 줄에서 사용되었다는 것을 확인할 수 있다.

 


 

참조변수 super

  • 조상 클래스의 인스턴스 본인을 가리키는 일종의 참조변수이다.
      * 참조변수 super에는 조상 클래스의 인스턴스의 주소값이 저장되어 있다.
  • 조상 클래스의 객체를 가리킨다는 점만 다르고, 그 외의 개념과 기능은 참조변수 this 의 그것과 동일하기 때문에 자세한 설명은 참조변수 this 의 설명을 참고하자.
  • 조상 클래스의 iv와 자손 클래스의 iv의 이름이 같을 때, 이 둘을 구분해야 할 때는 반드시 참조변수 super을 사용해야 한다.
      * 구분을 위해서 꼭 적어줘야 한다는 점 또한 참조변수 this와 개념이 비슷하다. 구분하는 대상만 서로 다를 뿐...

 


 

생성자 super()

  • 자손의 생성자 내부에서 조상의 생성자를 호출해야 할 때 사용하며, 개념과 기능은 생성자 this()와 동일하다.
     * 상속 시, 조상의 생성자와 초기화 블럭은 함께 상속되지 않는 다는 점을 기억해야한다. 그래서 조상의 생성자를 사용하기 위해서는 super()를 사용해야 하는 것이다.
  • 생성자 this()와 마찬가지로, super()를 사용하려면 생성자의 내부에서 첫줄에 사용해야 한다.

생성자 super() 를 사용해야 하는 경우는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Point {
    int x, y;
    Point(){}
    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
class Point3D extends Point {
    int z;
    Point3D(int x, int y, int z) {
        super(x,y);
//        this.x = x;
//        this.y = y;
        this.z = z;
    }
}
cs
  • Point3D(int x, int y, int z) 의 생성자에서 지역변수 x 와 y를 인스턴스변수 x 와 y 에 대입해야 할 때, 
    this.x = x; this.y = y; 와 같은 코드는 좋지 못하다.
  • 생성자 super()를 이용한 super(x, y)를 작성해서 조상의 생성자인 Point(int x, int y)를 호출한다.

 


 

생성자의 중요 개념 정리

  • 인스턴스가 생성될 때 마다 호출되는 인스턴스 초기화( = iv 초기화) 메서드
    * 객체의 생성은 생성자가 아니라, new 연산자의 역할임을 유의하자.
    * 생성자 또한 메서드 이다.
  • 생성자도 메서드라서 "오버로딩"이 가능하다.
     (클래스 내부에 여러 갯수의 생성자 작성이 가능한 것도 오버로딩 개념이 들어간 것)
     * 오버로딩 : 메서드 이름은 동일하고 매개변수의 개수 및 타입 및 순서가 다른 메서드를 여러 갯수 작성하는 것.
  • 모든 클래스는 반드시 최소한 1개 이상의 생성자를 가져야한다.
  • 클래스 내에 작성된 생성자가 없다면 컴파일러가 클래스 내에 기본생성자를 자동으로 추가해준다.
     * 기본생성자란, 매개변수가 없는 생성자를 말한다.
  • 매개변수가 존재하는 생성자를 작성해둔 경우, 컴파일러가 기본생성자를 자동으로 추가해 주지 않는다.
     * 이런 경우에는 작성자가 수동으로 기본생성자를 작성해야만 한다.
     * 기본생성자는 반드시 만들어 줘야 한다고 생각해두자 = 습관화!!
  • 모든 생성자는 반드시 생성자 내부의 첫 줄에 다른 생성자를 호출해야 한다.
  • 생성자 내부에 다른 생성자를 호출하는 코드를 작성하지 않는 경우, 컴파일러가 생성자 내부의 첫 줄에 조상의 기본 생성자인 super(); 를 자동 삽입해준다.
  • 생성자 this() 와 super()는 반드시 생성자 내부의 첫 줄 에서만 사용 가능하다.

 


 

생성자의 중요 개념을 바탕으로 다음 코드의 출력 결과를 예상해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Parent {
    int x = 100;
    Parent() {
        this(200);
    }
    Parent(int x) {
        this.x = x;
    }
    int getX() {return x;}
}
class Child extends Parent {
    int x = 3000;
    Child() {
        this(1000);
    }
    Child(int x) {
        this.x = x;
    }
}
cs
1
2
3
4
5
6
class Solution {
    public static void main(String[] args) {
        Child c = new Child();
        System.out.println("x = " + c.getX());
    }
}
cs

 


 

출력 정답 :

 x = 200

 


 

  1.  9행의 return x ; 는 Parent 에 있는 인스턴스 변수인 x 를  반환시킨다.
    ** Parent의 모든 멤버를 Child가 상속 받았는데 왜 getX() 메서드가 Child 인스턴스변수 x 를 반환하는 것이 아닌지는 더 알아봐야할듯 하다....
  2. Parent의 x 에는 어떤 값이 저장되어 있는지 추적해보자.
  3. Child() 생성자가 호출되었으므로 13~15행의 Child() { this(1000); } 가 호출된다.
  4. 14행의 this(1000)을 통해서, 16~18행의 Child(int x) { this.x = x; } 가 호출된다.
  5. Child(int x) { this.x = x; } 생성자 내부의 첫줄에는 다른 생성자를 호출하는 코드가 없기 때문에 컴파일러가 조상의 기본생성자인 super()를 자동삽입하여 조상의 기본생성자를 호출시킨다.
  6. 3~5행의 Parent() { this(200); } 가 호출된다.
  7. 4행의 this(200) 을 통해서, 6~8행의 Parent(int x) { this.x = x; } 가 호출된다.
  8. 지역변수 x 에 200 을 저장했으므로 this.x = x; 를 통해서 Parent의 인스턴스 변수 x 에 200이 저장된다.
  9. 따라서 x = 200 이 출력된다.

생성자 호출 과정만 정리하자면 다음과 같을 것이다.

Child() 호출  →  Child(int x) 호출  →  super() 즉 Parent() 호출  →  Parent(int x) 호출  →  super() 즉 Object() 호출

 

 


 

참조변수 this, super 의 개념을 활용하여 다음 코드의 출력을 예상해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Parent {
    int x = 100;
}
 
class Child extends Parent {
    int x = 200;
    
    void method() {
        System.out.println(x);
        System.out.println(this.x);
        System.out.println(super.x);
    }
}
cs

 

출력 정답 :

 200

 200

 100

 


  1. 9행의 x 는 this.x 와 동일한 코드이다. 왜냐하면, 컴파일러가 this. 을 자동추가 해주기 때문.(참조변수 this 개념 참고)
  2. 11행의 super.x는 조상의 인스턴스 변수 x 를 의미한다. (참조변수 super 개념 참고)

 

 

 

22년 12월 28일 수요일 학습