Java 생성자 - 도입
앞의 코드를 살펴보도록 한다. Student 클래스에서 initStudent 메소드가 있으며 Main 에서 매번 init 으로 학생으로 초기화를 해주어야 했다.
이러한 객체를 생성하고 초기화하는 작업이 반복되는 코드를 개선하기 위해 생성자(Construct) 를 사용해보도록 한다. 생성자는 객체를 생성하자마자 바로 필요한 메소드를 수행이 가능하도록 한다.
Student.java
public class Student {
String name;
int age;
int grade;
void initStudent(String name, int age, int grade) {
this.name = name;
this.age = age;
this.grade = grade;
}
}
Main.java
public class Main {
public static void main(String[] args) {
Student student1 = new Student();
student1.initStudent( "guest1", 14, 90);
Student student2 = new Student();
student2.initStudent( "guest2", 19, 70);
Student[] students = {student1, student2};
for (Student s : students) {
System.out.println("학생이름: " + s.name + ", 학생 나이: " + s.age + ", 학생 점수: " + s.grade);
}
}
}
Main 코드에서 객체를 생성하자마자 initStudent 메소드로 초기화하는 작업을 볼 수 있다.
객체를 생성하는 즉시 초기화 없이 필요한 기능을 수행하도록 생성자를 익혀보자.
생성자 생성 방법
생성자를 사용하는 방법은 클래스명과 똑같은 메소드를 만들어주면 된다.
MemberConstruct.java
public class MemberConstruct {
String name;
int age;
int grade;
MemberConstruct(String name, int age, int grade) {
System.out.println("생성자 호출 name = " + name + ", age=" + age + ", grade=" + grade);
this.name = name;
this.age = age;
this.grade = grade;
}
}
이 코드에서 다음 부분이 생성자다.
MemberConstruct(String name, int age, int grade) {
System.out.println("생성자 호출 name = " + name + ", age=" + age + ", grade=" + grade);
this.name = name;
this.age = age;
this.grade = grade;
}
생성자는 메소드와 비슷하지만 차이가 있다.
- 생성자의 이름은 클래스 이름과 동일해야함. 따라서 첫 글자로 대문자로 시작
- 생성자는 반환 타입이 없다. 비워두기
- 그 외 메소드와 동일하다.
다음으로 Main 클래스를 살펴본다.
Main.java
public class Main {
public static void main(String[] args) {
MemberConstruct m1 = new MemberConstruct("guest1", 14, 90);
MemberConstruct m2 = new MemberConstruct("guest2", 19, 80);
MemberConstruct[] members = {m1, m2};
for (MemberConstruct member : members) {
System.out.println("이름: " + member.name + ", 나이: " + member.age + ", 점수: " + member.grade);
}
}
}
실행결과
생성자 호출 name = guest1, age=14, grade=90
생성자 호출 name = guest2, age=19, grade=80
이름: guest1, 나이: 14, 점수: 90
이름: guest2, 나이: 19, 점수: 80
생성자 호출
생성자를 호출 하는 방법은 new 명령어 다음에 생성자 이름과 매개변수를 맞춰 인수를 전달한다.
new 생성자/클래스이름( 생성자/클래스와 맞는 인수목록 )
Main클래스에서 MemberConstruct m1 = new MemberConstruct("guest1", 14, 90);
인수 값으로 넘겨 주고 있다. 이는 MemberConstruct 클래스에서 생성자를 만들 때 파라미터와 맞추기 위함이다. Java는 이 객체를 생성하고 메모리에 만들어지자마자 MemberConstruct(String name, int age, int grade)
인스턴스 생성자를 호출한다.
즉, 정리하면 다음과 같은 순서다
- 객체를 생성과 동시에 클래스의 생성자 확인
- 생성하면서 new MemberConstruct("guest1", 14, 90) 인수 값의 조건 확인
- MemberConstruct 생성자를 메모리로 불려와 코드 블록을 실행함
참고로 new 명령어를 실행할 때 (); 괄호를 넣게 되는데, 그 이유가 생성자 때문이다. 아무 역할이 없는 빈 생성자로 객체를 생성하면 생성자를 동시에 호출한다는 의미이다.
생성자 장점
생성자 장점으로 중복 호출을 줄일 수 있고, 조건을 강제할 수 있다.
중복 호출 제거
생성자가 없을 때의 코드는 다음과 같이 어떤 작업을 수행하기 위해서는 메소드를 한번 더 호출한다.
생성자가 없는 경우 - 중복 호출
MemberInit member = new MemberInit();
member.initMember("guest", 14, 90);
생성자 사용 - 중복 호출 제거
MemberConstruct member = new MemberConstruct("guest1", 14, 90);
제약사항 - 생성자 호출 조건 필수
생성자가 없는 경우 코드로 iniMember(...)
메소드를 호출하지 않아도 동작하나, 생성된 member 인스턴스에는 아무런 값이 없는 상태가 된다. 뒤늦게 해당 인스턴스를 사용한 경우 자바는 크래쉬가 발생되어 시스템에 큰 문제가 발생한다.
생성자는 객체를 생성할 때 직접 정의한 생성자를 반드시 호출한다.
앞서 만든 코드에서 다음과 같이 생성자를 호출하면 오류가 발생할 것이다.
MemberConstruct member = new MemberConstruct();
자바를 빌드하면 컴파일이 조건이 필요하다고 알려주므로 인수 값을 채워 해결할 수 있다. 즉, 필수 값을 보장한다.
참고: 생성자는 오버로딩이 가능하다.
다만, 객체 생성시 오버로딩한 생성자 하나만 호출한다.