개발새발

[Java] 생성자와 this 본문

Java/개념을 Java

[Java] 생성자와 this

칸쵸. 2023. 9. 11. 02:04
728x90

지금껏 코딩을 하면서 생성자가 뭔지도 정확히 개념도 안 잡혔고, 그냥 쓰라니까 쓰기는 하는데 이게 왜.. 필요한지도 이해가 잘 안됐다. 그냥 그런가보다 하고 넘기기에는 너무 자주 쓰는 것같고..해서 다시 공부한 결과~

 


1. 생성자

인스턴스가 생성 될 때마다 호출되는 인스턴스 초기화 메서드

아무든 메서드의 일종이다

 

개발자가 직접 생성자를 생성하지 않으면 기본적으로 디폴트(기본) 생성자가 자동으로 생성되는데, 얘는

클래스이름 () {}

과 같은 모양새를 가지고있다. 

( ) ← 일단 소괄호 안이 공란으로, 매개변수가 없다는 것이 가장 큰 특징.

 

위에서 말한대로 클래스 내에 생성자가 하나도 존재하지 않으면 컴파일러가 자동으로 추가해준다.

(단, 생성자가 하나라도 존재할시에는 자동 추가가 되지 않음. 필요하면 직접 타이핑해서 생성해야 됨)

 

그렇다면 그냥 기본 생성자만 있어도 되는데.. 왜 굳이 개발자는 다른 생성자를 또 만드는거지

결론부터 말하자면 귀찮아서라는 이유가 가장 큰 것같다. 워딩이 좀 없어보이기는한데 나름대로 추론한 결과 이것만큼 확실한 이유도 없는 것같아서 

 

예를 들어봅시다

public class Time() {
	int hour;
    int minute;
    int second;
    
    public Time() {} //디폴트 생성자
    //자동으로 생성되는거긴 한데, 일단 그냥 눈에 보이게 타이핑 해둠
}
public class TimeTest {
	public static void main(String[] args) {
		Time t = new Time(); //Time() : 기본생성자로 클래스 생성한 후
		//ex t라는 변수에 1시 34분 56초라는 시간을 저장하고싶다
		t.hour = 1;
		t.minute = 34;
		t.second = 56; // 인스턴스 변수 값을 따로 초기화
	}
}

위의 예시와 같이 t에 시간 정보를 저장하려면 두 단계를 거쳐야한다

1) 기본생성자 Time()을 통해 클래스 생성

2) 멤버변수 모두 초기화

 

지금이야 큰 문제는 없지만..

하지만 클래스에 멤버변수가 매우매우매우 많은 경우라면? 그리고 인스턴스가 t 하나로 끝나지 않고 여러개를 생성해야된다면? 1단계만해도 힘든데, 매번 클래스를 생성 할 때마다 수많은 멤버변수를 일일이 입력하면서 초기화하고 있으면 너무 힘들 것같다.

 

그런데 만약 1) & 2) 단계를 한 번에 끝낼 수 있는 방법이 있다면?

public class Time() {
	int hour;
    int minute;
    int second;
    
    public Time(int hour, int minute, int second) { //시간, 분, 초를 매개변수로 받는 생성자
    	this.hour = hour;
        this.minute = minute;
        this.second = second;
    }
}

매개변수에 대한 조건이 없던 디폴트 생성자와는 다르게, 아싸리 시간, 분 그리고 초 단위를 모두 매개변수로 받아햐하는 생성자 Time이 만들어졌다! 그렇게 되면

public class TimeTest {
	public static void main(String[] args) {
		Time t = new Time(1,34,56); //1시 34분 56초가 뚝딱
	}
}

아까처럼 일일이 모든 인스턴스 변수에 대해 초기화가 필요했던 디폴트 생성자와 다르게, 코드 한 줄로 클래스 생성 및 인스턴스 변수 초기화가 뚝딱 끝난 모습을 볼 수 있다~

 

**주의: 이때 만들어진 생성자 Time은 애초에 시간, 분, 초 모두를 매개변수로 받는다고 선언했기 때문에, 클래스를 생성할 때 하나라도 누락되는 값이 있으면 작동 안함

(해결책: 누락값 없이 모두 입력하든지.. 디폴트 생성자를 직접 타이핑해서 만들든지)

 

**생성자 만들 때 규칙

 

1) 생성자의 이름 = 클래스 이름

클래스이름 (타입 변수명, 타입 변수명, ...) {
	//인스턴스 생성 시 수행될 코드
    //주로 인스턴스 변수의 초기화 코드를 적는다
}

2) 리턴값이 없다. (따라서 void도 붙이지 않음)

 생성자는 인스턴스 변수를 초기화하는 것만이 기능이기 때문에 애초에 반환하는 값이 존재하지 않음..

 

3) 모든 클래스는 반드시 생성자를 가진다

 개발자가 생성자를 따로 만들지 않는 이상 자동으로 디폴트 생성자가 만들어지긴 함.

 

2. 참조변수 this

이 친구가 제일 이해가 안됐던 예약어 중 하나. 지금은 얼추 이해가 됐지만 글을 이어서 쓰기에 너무 졸리고 배고파서 내일 다시 이어서 쓰겠음요...

 

먹고자

20230911 이어서 씁니다

 

내가 그동안 this 예약어에 대해서 왜 이렇게 감을 못 잡는가 생각도 해보고, 공부도 조금 해본 결과 내린 결론.

this라는 예약어에는 크게 두 가지 사용 법이 있는데

 

1) 참조변수 this: 자신의 메모리를 가리킨다

2) 생성자 this() : 생성자에서 다른 생성자를 호출한다

 

일단 나는 그동안 두 경우의 this 예약어를 혼동했고, 그 전에 각 사용법마다 기능도 정확히 인지하지 못해서 더더욱 어려워했던 것같다. 사실 둘은 예약어만 동일할 뿐 기능은 아예 다른 별개의 것이라고 생각하면 차라리 이해하기는 편하더라.

그럼 각자의 용도에 대해 설명을 해보자.

 

1) 참조변수 this

기능만 설명을 하자면 생성된 인스턴스 스스로를 가리키는 예약어라고 볼 수 있다.

그럼 또 나는 기계적으로 this. 을 찍고있으면서도 머릿속으로는 생각했던 것이다.

 

'아니 인스턴스를 만들었으면 그냥 쓰면되지 뭐하러 자기를 또 가리키는거야?'

 

아래 코드 예시를 보자

package thisEx;

public class Number{
	int a, b; // this.a, this.b
    
    public Number(int a, int b) { //생성자
    	this.a = a; //인스턴스 변수와 지역변수를 구별하기 위해 this 사용
        this.b = b;
    }
  
}

클래스의 생성자 Number(int a, int b) {...} 를 보면, a와 b라는 매개변수이자 지역변수가 선언되어있다.

변수의 종류에 대해서는 또 추후에 정리해야지... 아무튼

 

그렇다면 이 생성자 내의 this.a = a; 코드는 단순히 'a는 a이다'라는 당연한 말일까?

결론부터 말하자면 좌변의 a와 우변의 a는 각각 가르키는게 다른 변수다.

 

좌변 this.a에서의 a : class를 생성하면서 만든 멤버변수이자 인스턴스 변수 a

우변에서의 a : 생성자를 만들면서 선언한 매개변수이자 지역변수 a

 

둘의 이름이 같은데 만약 좌변을 그냥 a로 방치해두면 사용자 입장에서도 이게 인스턴스 변수인지 지역변수인지 어떻게 알며, 컴퓨터가 보기에도 "지역변수 a = 지역변수 a 라고?"가 되는 것이다.

 

즉, 매개변수 a로 입력받아서 인스턴스 변수인 a에 대입함으로써 Number클래스를 생성하려는 생성자의 의도가 전혀 전달되지 않는다.  그래서 "이 a는 인스턴스 변수입니다~ (지역변수 아님요)" 하고 명시할 수 있는 this. 가 필요한 것.

 

즉, 참조변수로서의 tihs. 는 인스턴스 변수와 지역변수를 구분하기 위해 쓴다고 볼 수 있는 것이다.

 

2) 생성자 this()

같은 클래스 내 생성자가 여러 개 있을 때 어떤 생성자에서 다른 생성자를 호출하는 경우에 쓰는 방법이다.

예를 들어서

class Pokemon {
	//멤버변수 선언
	String name; //포켓몬 이름
    int roadNum; //서식하는 도로번호
    
    //생성자 선언
    Pokemon() { //this를 사용해 Pokemon(String, int) 생성자 호출
    	this("갸라도스", 227);
    }
    
    Pokemon(String name, int roadNum) {
    	this.name = name;
        this.roadNum = roadNum;
    }
}

이때의 this()는 다른 생성자를 호출하기 위한 기능으로서, 앞의 참조변수 this. 와는 아예 다르다. 혼동하지 말 것~

이것도 왜 굳이 번거롭게 호출을 해가며 쓰냐고 하면, this를 사용하여 생성자를 호출하면 코드 중복을 줄일 수 있다는 장점이 있기 때문이다. (코드 추가 설명은 나중에.)

 

**주의: this를 사용하여 생성자를 호출하는 코드 이전에 다른 코드는 넣을 수 없다.

 

'Java > 개념을 Java' 카테고리의 다른 글

[Java] 배열과 리스트 1 : Array ~ 다차원 배열  (1) 2023.09.18
[Java] API  (1) 2023.09.14
[Java] 추상클래스 Abstract  (0) 2023.09.12
[Java] 변수의 종류  (0) 2023.09.12
[Java] 클래스와 객체  (0) 2023.09.11