생성자(Constructor)는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드' 이다. 인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다. 생성자 역시 메서드처럼 클래스 내에 선언되며, 구조도 메서드와 유사하지만 리턴값이 없다는 점이 다르다. 그렇다고 해서 생성자 앞에 리턴값이 없음을 뜻하는 키워드 void를 사용하지 않는다. 이유는 모든 생성자가 리턴값이 없기 때문에 생략가능하게 만들어 둔 것 !
기본 생성자(default constructor)
Class를 활용하기 전까지 나는 생성자를 모르고 프로그래밍 해왔지만 사실 모든 클래스에는 반드시 하나 이상의 생성자가 정의되어 있어야 한다. 내가 생성자를 정의하지 않고도 인스턴스를 생성할 수 있었던 이유는 컴파일러가 제공하는 '기본 생성자' 가 있었기 때문이다.
기본 생성자의 특징
1. 매개 변수 없음 : 기본 생성자는 매개변수를 받지 않는다.
2. 자동 생성 : 사용자가 클래스 내에 어떠한 생성자도 정의하지 않았을 때, 컴파일러가 자동으로 기본 생성자를 추가한다.
3. 기본 초기화 : 기본 생성자는 객체의 멤버 변수를 기본값으로 초기화한다. (예: 정수형은 0, 부울형은 false, 객체 참조형은 null)
매개변수가 있는 생성자
생성자도 메서드처럼 매개변수를 선언하여 호출 시 값을 넘겨받아서 인스턴스의 초기화 작업에 사용할 수 있다. 인스턴스마다 각기 다른 값으로 초기화 되어야 하는 경우가 많기 때문에 매개 변수를 사용한 초기화는 매우 유용하다.
아래의 코드는 Animal 인스턴스를 생성시 생성자만 사용했을 경우와 매개변수가 있는 생성자의 차이점을 보여준다.
b의 경우 인스턴스를 생성한 다음에 인스턴스 변수들을 따로 초기화 해주어야 하지만, a의 경우 인스턴스를 생성하는 동시에 원하는 값으로 초기화를 할 수 있다. 인스턴스를 생성한 다음에 인스턴스 변수의 값을 변경하는 것보다 매개변수를 갖는 생성자를 사용하는 것이 코드를 보다 간결하고 직관적으로 만들 수 있다.
생성자에서 다른 생성자 호출하기 - this(), this
this 와 this() 는 객체 또는 생성자를 참조할 때 사용되지만, 사용 목적과 방식에 차이가 있다. 같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 생성자 간에도 서로 호출이 가능하다. 단, 다음의 두 조건을 모두 만족해야 한다.
1. 생성자의 이름으로 클래스 이름 대신 this 를 사용한다.
2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫줄에서만 호출이 가능하다.
생성자에서 다른 생성자를 첫 줄에서만 호출이 가능하도록 한 이유는 생성자 내에서 초기화 작업 도중에 다른 생성자를 호출하게 된다면, 호출된 다른 생성자 내에서도 멤버변수들의 값을 초기화 할 것이므로 다른 생성자를 호출하기 이전의 초기화 작업이 무의미해질수 있기 때문이다. 아래의 코드는 생성자 생성시의 코드와 출력값을 보여준다.
1. 생성자 생성시 초기값을 저정해주지 않았을 경우
2. 생성자 생성시 this() 를 사용하지 않았을 경우
3. 생성자 생성시 this() 를 사용한 경우
첫번째의 경우 초기값을 정해주지 않았기 때문에 출력시에 null 과 0 이 출력 된 것을 확인할 수 있다. (string은 null, boolean은 false, int는 0 이 default 값이다.)
두번째의 경우 초기값을 지정해주었기 때문에 출력시에 지정된 초기값으로 출력 되는 것을 확인 할 수 있다.
세번째의 경우 두번째와 같은 코드이지만 더 간략하게 표현할 수 있음을 확일할수 있다 !
같은 클래스 내의 생성자들은 일반적으로 서로 관계가 깊은 경우가 많아 서로 호출하도록 하여 유기적으로 연결해주면 더 좋은 코드를 얻을 수 있다. 그리고 수정이 필요한 경우에도 보다 적은 코드만을 변경하면 되므로 유지보수가 쉬워진다. 아래의 코드는 this의 사용 예시이다 !
왼쪽 코드의 'animalType = at;' 는 생성자의 매개변수로 선언된 지역변수 at의 값을 인스턴스변수 animalType 에 저장한다. 이 때 변수 at 와 animalType 은 이름만으로도 서로 구별 되므로 아무런 문제가 되지 않는다. 하지만, 오른쪽 코드에서처럼 생성자의 매개변수로 선언된 변수의 이름이 동일할 경우 이름만으로는 두 변수가 서로 구별되지 않는다. 이런 경우에 인스턴스변수 앞에 this 를 사용하여 구별해준다. 이렇게 된다면 this.animalType 은 인스턴스 변수이고, animalType 은 생성자의 매개변수로 정의된 지역변수로 서로 구별이 가능하다.
이처럼 생성자의 매개변수로 인스턴스변수들의 초기값을 제공받는 경우가 많기 때문에 매개변수와 인스턴스변수의 이름이 일치하는 경우가 자주 있다. 따라서 이 경우 왼쪽 코드와 같이 매개변수 이름을 다르게 하는 것 보다 this 를 활용하여 구별되도록 하는 것이 의미가 더 명확하고 이해하기 쉽다.
'Java' 카테고리의 다른 글
[Java] 다형성 (Polymorphism) (0) | 2024.04.26 |
---|---|
[Java] 오버로딩 & 오버라이딩(Overloading & Overriding) (0) | 2024.04.09 |
[Java] Getter&Setter (0) | 2024.03.31 |
[Java] 접근 제어자(Access Modifiers) (0) | 2024.03.26 |
[Java] 스택(Stack)과 힙(Heap) (0) | 2024.03.24 |