Java 18. 생성자
생성자
우리는 프로그램을 만들 때 변수를 선언하고 반드시 초기화를 해주어야 한다고 알고있다. 만약 초기화를 하지 않으면 해당 변수에는 쓰레기값이 들어가게 되고 심한 경우에는 초기화 오류가 발생하기 때문이다.
이와같이 변수의 초기화를 진행하는 프로세스를 클래스에 대입한 개념으로, 객체를 호출할 때 클래스는 생성자를 통해 객체를 초기화 하게 되는데 구현 방법에 따라 기본생성자, 묵시적 생성자, 명시적 생성자로 나뉘게 된다.
여기서 객체의 초기화란 클래스가 객체를 생성/호출하였을 때, 객체의 필드를 초기화 하거나 메소드를 호출해서 객체가 사용할 준비를 하는 것으로 일련의 준비단계라고 생각하면 쉽다.
생성자 : 클래스로부터 객체를 생성할 때 수행되어 객체의 초기화를 담당하는 것.
- 생성자는 리턴타입을 갖지 않는다.
- 생성자는 클래스 이름과 동일해야 한다.
- 모든 클래스는 생성자가 반드시 존재하며, 하나 이상을 가질 수 있다.
- 클래스 내부에 생성자를 선언하지 않으면 자동으로 기본 생성자가 선언된다.
- 클래스 내부에 파라미터가 없는 생성자를 선언하는 경우 이를 묵시적 생성자라 한다.
- 클래스 내부에 파라미터가 있는 생성자를 선언하는 경우 이를 명시적 생성자라 한다.
기본 생성자
public class Sub1 {
// public Sub1() {}
public int iNum1 = 0;
// 생성자가 명시되어있지 않으므로 기본 생성자가 선언된다.
}
기본 생성자는 클래스 내부에 어떠한 생성자도 없을 시 객체 생성 과정에서 컴파일러가 자동으로 추가하는 생성자다.
왜 굳이 의미도 없는 기본 생성자를 선언해주느냐 함은 클래스에서 생성자가 없으면 객체에 접근 자체를 하지 못한다.
메모리 구조상 new 연산자가 생성자를 정상적으로 실행시키면 힙(heap)영역에 객체가 생성되고, 생성된 객체의 주소가 클래스 타입 변수에 리턴되어 객체에 접근할 수 있게 되는데 생성자가 실행되지 않으면 힙 영역에 객체가 생성되지 않으니 객체의 주소도 리턴받을 수 없다.
따라서 객체를 사용하기 위해서는 반드시 생성자가 필요하고 생성자를 명시하지 않았을 때는 자동으로 기본생성자가 선언된다.
기본 생성자 + 메소드
public class Sub {
// public Sub(){}
public int Sum(int iNum1, int iNum2){
// 생성자 없이 메소드만 구현되어 있으므로 기본 생성자로 선언된다.
int sum = iNum1 + iNum2;
return sum;
}
}
위와같이 생성자 없이 메소드만 구현되어있는 경우에도 컴파일러가 기본 생성자를 추가하므로 정상적인 프로그램 구동이 가능하다.
묵시적 생성자
public class Sub2 {
public Sub2(){
// 파라미터가 없는 묵시적 생성자
System.out.println("묵시적 생성자");
}
}
묵시적 생성자는 파라미터를 갖지않는 생성자다. 기본 생성자와의 차이점은 보다 원하는 방식으로 초기화를 할 수 있다는 점이다.
하지만 파라미터를 받지 않으므로 초기화의 개념이 명시적 생성자 보다 상대적으로 떨어진다.
명시적 생성자
public class Sub3 {
public Sub3(String s){
// 파라미터 값을 받는다.
System.out.println(s);
}
}
명시적 생성자는 객체 생성시 초기화를 위한 파라미터를 받으며 객체가 실행될 때 받은 값으로 초기화가 진행된다.
Sub3 sub3 = new Sub3("명시적 생성자"); // 명시적 생성자
//객체를 생성할 때 String 변수에 파라미터를 줌으로써 String s는 "명시적 생성자"로 초기화된다.
명시적 생성자를 만드는 이유
생성자 내부에는 어떠한 작업을 하는 코드는 쓸 수 있다.
즉, 인스턴스가 만들어지는 그 순간에 생성자 내부에 작성한 어떠한 작업을 해줄 수 있는 것이다.
그래서 명시적으로 생성자를 만드는 이유는,
인스턴스 변수를 초기화 할때, 0,false,null이 아닌 값으로 설정하기 위해서 이거나
매개변수로 값을 넘겨받아 객체를 다양하게 초기화 하기 위해서 이거나
인스턴스가 생성될 때 수행되어야하는 작업이 있기 때문이다.
즉, 필드에 초기값을 저장 하거나 메소드를 호출하여 객체 사용 전에 필요한 준비를 한다고 보면 된다.