[Java] #16 this/this()

febCho·2023년 11월 12일
0

Java

목록 보기
38/53

비슷해 보이는 this와 this()는 그 쓰임이 완전히 다르기에 구별해 기억해야 한다.
그리고 this는 예약어이기 때문에 패키지명으로 사용할 수 없다.
this는 패키지명이라 사용 불가

1. this

package kr.s16.object.thistest;

public class ThisMain01 {
	//생성자
	public ThisMain01() {
		System.out.println("객체 생성: " + this);
	}
	
	public static void main(String[] args) {
		ThisMain01 tm = new ThisMain01();
		System.out.println("객체 생성 후 : " + tm);
		
	}
}

this객체 내부에서 객체를 지칭할 때 사용할 수 있고 일종의 참조변수 역할을 함.
객체의 구성원(필드, 메서드)을 호출할 때 사용

  1. 생성자를 오버로딩하여 객체가 생성되는 시점에 this를 출력하도록 한다.
  2. ThisMain01 tm = new ThisMain01(); 메인 영역에서 ThisMain01 객체를 생성한다.
  3. 또한, 메인 영역에서 객체의 참조변수(tm)을 호출한다.
  4. 출력 결과는 다음과 같다.
    this는 참조변수 역할을 하기에 객체 내부에서 'this'를 사용할 경우, 객체 외부에서 참조변수를 호출했을 때와 같은 결과를 출력할 수 있다.
출력)
객체 생성: kr.s16.object.thistest.ThisMain01@372f7a8d
객체 생성 후 : kr.s16.object.thistest.ThisMain01@372f7a8d
  1. 이를 그림으로 정리하면 다음과 같다.
    this

package kr.s16.object.thistest;

class ThisTest{
	//은닉화
	private int a;//멤버 변수
	
	//캡슐화
	public void setA(int a) {
		this.a = a;
	}
	public int getA() {
		return a;
	}
}
public class ThisMain02 {
	public static void main(String[] args) {
		ThisTest tt = new ThisTest();
		tt.setA(10);
		System.out.println(tt.getA());
	}
}
  1. 또한, 메서드 내에서 변수명이 충돌할 경우 멤버 변수보다 지역 변수가 우선한다는 규칙에 의해 아래 이미지와 같이 코드를 전개할 시 a는 전부 지역 변수를 지칭하는 것이 되어 멤버 변수 명을 인식하지 못하는 문제가 발생한다.
    this 없으면
    따라서 은닉화된 멤버 변수에 접근할 때도 this를 사용한다. 멤버 변수는 메서드가 종료되어도 객체 내에서 살아 있으나, 지역 변수는 메서드가 종료되면 사라져 setA 메서드에서 언급된 this.a는 멤버 변수인 private int a이기 때문이다.

    this.a : 멤버 변수
    a : 지역 변수

  2. 위와 같은 과정을 통해 은닉화된 멤버 변수 private int a에 접근, setA() 메서드가 인자로 받은 int a를 대입해줄 수 있게 되고, getA() 메서드 호출 시 이러한 멤버 변수를 return 할 수 있게 된다.
    물론 아래와 같이 this를 사용하지 않고 코드를 전개해도 문제가 되지는 않는다.

package kr.s16.object.thistest;

class ThisTest{
	//은닉화
	private int a;//멤버 변수
	
	//캡슐화
	public void setA(int n) {
		a = n;
	}
	public int getA() {
		return a;
	}
}
public class ThisMain02 {
	public static void main(String[] args) {
		ThisTest tt = new ThisTest();
		tt.setA(10);
		System.out.println(tt.getA());
	}
}

단, 지금과 달리 멤버 변수가 많고 이를 모두 은닉화하여 개별의 setA() 메서드를 만들어야 하는 상황이라면 이야기가 달라진다.
ex. 은닉화된 멤버 변수 20개 → 그와 상이한 setA() 메서드 내 지역 변수 20개 : 총 40개의 명칭

위 예시와 같이 멤버 변수 20개와 전부 다른 명칭을 가진 지역 변수를 명시하는 것은 비효율적이다. 따라서 멤버 변수와 동일하게 만드는 것이 효율적인 셈이다.
ex. 은닉화된 멤버 변수 20개 → this를 활용해 지역 변수 명을 동일하게 함 : 총 20개의 명칭

참고) 은닉화/캡슐화
참고) 멤버 변수/지역 변수


2. this()

package kr.s16.object.thistest;

public class ThisMain03 {
	public ThisMain03() {
		this("바람");
	}
	public ThisMain03(int a) {
		//System.out.println("~~~~~~~~");
		this(String.valueOf(a));//int -> String
		System.out.println("============");
	}
	public ThisMain03(String s) {
		System.out.println(s);
	}
	public static void main(String[] args) {
		ThisMain03 tm = new ThisMain03();
		ThisMain03 tm2 = new ThisMain03(10000);
		ThisMain03 tm3 = new ThisMain03("Korea");
	}
}

this()생성자 내부에서 또 다른 생성자를 호출할 때 표시함.
생성자 내부에 반복적인 코드가 있어서 반복적인 코드를 제거하고 기존 코드를 재사용하고자 할 때 사용한다.

  1. 메서드 역시 재활용성을 높이기 위해 한 메서드 안에서 중복되는 다른 메서드를 호출하기도 했다. 이러한 것을 모듈화라고 하며, 생성자 역시 중복되는 부분을 모듈화 하여 재활용성을 높이기 위해 this()를 사용한다.
    (메서드와 달리, 객체 내부에서 자기 자신의 이름을 부르지 않으니 'this()'라고 칭함)

  2. 위 예제는 public ThisMain03(String s){System.out.print(s);} 생성자를 모듈화하여 this()로 지칭, 생성자 오버로딩을 통해 총 3가지 생성자를 만들었다.

public ThisMain03(){this("바람");}의 경우 String 타입의 데이터(바람)을 this()에 넣어주어 객체를 생성하면 System.out.println("바람");이 동작하게끔 하였고,

public ThisMain03(int a){this(String.valueof(a));}의 경우 인자로 정수형 타입의 데이터(int a)를 전달 받으면, 그것을 String.valueof()를 통해 String 타입의 데이터로 변환, 객체 생성 시 System.out.println(String.valueof(3000)); 출력하고자 했다.

  1. 따라서 출력 결과는 다음과 같으며
바람
10000
============
Korea

이때, this() 앞에는 다른 코드가 올 수 없다. 생성자 내부적으로도 this();를 초기화라고 인식하기 때문이다.
this() 앞에 수행문 명시 불가

profile
Done is better than perfect.

0개의 댓글