자바로 코딩을 하다 보면, 당연하게 쓰는 메서드들이 정확히 어떤 역할을 하는 지, 왜 사용하는 지 문득 헷갈리거나 까먹을 때가 있습니다🤔
그래서 오늘은 생성자의 정확한 역할과 개념을 정리해보면 좋을 거 같아서 같이 한 번 알아보겠습니다🐱
먼저 위키피디아에 명시되어 있는 생성자의 정의는 다음과 같습니다.
생성자(Contructor)는 객체 지향 프로그래밍에서 객체의 초기화를 담당하는 서브루틴을 가리킨다. 생성자는 객체가 처음 생성될 때 호출되어 멤버 변수를 초기화하고, 필요에 따라 자원을 할당하기도 한다. 객체의 생성 시에 호출되기 때문에 생성자라는 이름이 붙었다.
생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드이고, 인스턴스 변수의 초기화 작업에 주로 사용됩니다.
생성자 역시 메서드처럼 클래스 내에 선언되며, 구조도 메서드와 유사하지만 리턴 값이 없다는 점이 다릅니다.
생성자는 다음과 같이 정의합니다.
생성자도 다른 메서드들과 같이 오버로딩이 가능하므로 하나의 클래스는 여러 개의 생성자를 가질 수 있습니다.
class Constructor {
// 매개변수가 없는 생성자
Constructor() {
// ...
}
// 매개변수가 있는 생성자
Constructor(int a, int b) {
// ...
}
}
그리고 new
연산자를 통해 인스턴스를 생성하게 되면, 생성자가 호출되어 초기화 작업을 수행하게 되는 것이죠
Constructor c = new Constructor();
/**
- 연산자 new에 의해서 메모리 (heap) 에 해당 클래스의 인스턴스가 생성된다.
- 생성자가 호출되어 초기화 등의 작업을 수행한다.
- 연산자 new의 결과로 생성된 인스턴스의 주소를 참조변수에 저장한다.
**/
명시적으로 생성자를 정의하지 않고도 인스턴스를 생성할 수 있습니다.
이는 컴파일러가 '기본 생성자(default constructor)'를 제공하기 때문이죠.
컴파일러가 자바 소스 파일을 컴파일 할 때, 만약 클래스에 생성자가 없다면 자동적으로 기본 생성자를 추가하여 컴파일을 합니다.
// 기본 생성자는 아무 매개변수도 없고 내용도 없는 간단한 생성자이다.
class Example {
// 클래스에 명시적으로 구현된 생성자가 없다면 이와 같은 기본 생성자가 추가되어 컴파일된다.
Example() {}
}
❗여기서 클래스의 접근 제어자(access modifier)가 public인 경우에는, 기본 생성자도 public으로 추가됩니다.
그리고 아래와 같은 경우도 주의해야 합니다.
class Example {
int val;
Example(int x) {
val = x;
}
}
public class ExampleTest {
public static void main(String[] args) {
Example ex = new Example(); // compile error 발생
}
}
Example
클래스를 보면 이미 Example(int x)
라는 생성자를 가지고 있습니다. 그래서 컴파일러는 이미 생성자가 존재하기 때문에 기본 생성자를 추가해주지 않습니다.
하지만 main
함수에서 기본 생성자를 이용해 인스턴스를 생성하려 하기 때문에 여기서 에러가 발생하는 것이죠.
생성자도 다른 메서드들과 같이 매개변수를 선언하여 사용할 수 있습니다.
class Example {
int value1;
int value2;
Example() {}
Example(int a, int b) {
value1 = a;
value2 = b;
}
}
여기서 int a
와 int b
를 매개변수로 가지는 생성자는 인자들을 입력받아 멤버 변수인 value1
, value2
를 초기화하는데 사용합니다.
생성자 안에서 다른 생성자를 호출하는 것도 가능합니다.
하지만 다음 조건을 만족시켜야 합니다.
this
키워드를 사용한다.다른 생성자 호출 시에 첫 줄에서만 가능한 이유는 생성자 내에서 초기화 작업 도중에 다른 생성자를 호출하게 되면, 호출된 다른 생성자 내에서도 멤버 변수들의 값을 초기화 할 것이므로 다른 생성자를 호출하기 이전의 초기화 작업이 무의미해질 수 있기 때문입니다.
this
는 참조변수로 인스턴스 자신을 가리킵니다.
참조변수를 통해 인스턴스의 멤버에 접근할 수 있는 것처럼 this
로 인스턴스 변수에 접근할 수 있습니다.
class Exampled {
int value1;
int value2;
Exampled(int value1, int value2) {
this.value1 = value1;
this.value2 = value2;
}
}
이 예제와 같이 해당 인스턴스의 멤버 변수에 접근하기 위해 this
를 사용할 수 있습니다.
생성자 안의 value1
과 value2
가 여러 의미로 사용되는데, this
를 붙인 변수는 클래스에 선언된 인스턴스 변수들이고, 다른 value1
, value2
는 매개변수로 입력받은 지역변수 입니다.
이처럼 this
키워드를 이용하여 인스턴스의 변수 초기화에 사용할 수 있습니다.
현재 사용하고 있는 인스턴스의 값을 복사하여
같은 값을 가지는 인스턴스를 만들 때 생성자를 사용할 수 있습니다.
class Example {
int value1;
int value2;
Example(int value1, int value2) {
this.value1 = value1;
this.value2 = value2;
}
Example(Example ex) {
this(ex.value1, ex.value2);
}
}
Example
객체를 인스턴스 생성시에 생성자의 매개변수로 주는 경우, 같은 클래스 안에 있는 다른 생성자를 호출하여 해당 인스턴스의 값을 초기화 해줄 수 있습니다.
이렇게 인스턴스의 값을 동일하게 가지고 있는 다른 인스턴스를 생성할 수도 있습니다.
📚Reference
생성자 - 위키피디아
생성자 - jammmm's tistory