-생성자를 실행시키지 않고는 클래스로부터 객체를 만들 수 없다
-new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되며, 객체의 초기화를 담당한다
(객체 초기화 : 필드를 초기화하거나, 메소드를 호출해 객체를 사용할 준비하는 것을 말한다.)
생성자 종류
1. 기본 생성자 : 클래스명(){ }
2. 명시적 생성자 : 클래스명(자료형 변수형, 자료형 변수형){ }
모든 클래스에는 생성자가 반드시 존재하며, 하나 이상 가질 수 있다
Person(){
}
// 중괄호가 비어있는 기본 생성자이다
// 생성자 선언이 따로 없다면 컴파일러는 이러한 생성자를 자동 추가한다.
기본 생성자에 초기화 내용을 넣을 수도 있다
public class Ch06_1 {
// 필드 : 학변, 이름, 전공, 지도교수코드, 점수
// 용도 : 자료를 변수에 넣기
String number = null; // 학번
String name = null; // 이름
String dept = null; // 전공
int teacherCode = 0; // 지도교수 코드
double score = 0; // 점수
boolean gen;
Ch06_1(){
// 기본 생성자에 값 넣기
number = "2021";
name = "오늘";
dept = "computer";
teacherCode = 88;
score = 98;
gen = true;
}
}
// main
Ch06_1 student = new Ch06_1();
System.out.println(student.number + ", "+student.name);
실행 결과
필드에 변수 선언해줄때 number와 name은 null로 초기화와 동시에 선언해주었음에도 main에서 출력해보면 기본 생성자에 넣어놓은 값으로 출력되는 것을 알 수 있다.
명시적으로 생성자를 선언하는 이유는 객체를 조금 더 다양하게 초기화하기 위해서이다.
클래스(매개변수 선언, …){
// 객체의 초기화 코드
}
매개변수는 new 연산자로 생성자를 호출할 때 외부 값을 생성자 블록 내부로 전달하는 역할을 한다. 예를 들어 메인에서 Ch06_1 생성자를 호출할 때 년도와 이름이라는 두개의 값을 제공한다고 보자
// main
Ch06_1 student2 = new Ch06_1("1988", "한태주");
이런 식으로 작성할 수 있다. 두 매개는 모두 String 타입이고, 이러한 매개값을 받을 수 있으려면
public class Ch06_1 {
Ch06_1(String num, String na){ … }
}
이런식으로 작성해줘야한다. String을 두 개 받을 수 있도록 작성해주는 것이다.
// main에서 전해준 매개변수
// Ch06_1 ex3 = new Ch06_1(5.5, true);
// 저 매개변수를 받기위한 작성
public class Ch06_1 {
Ch06_1(double num, boolean gender){ … }
}
이 경우에는 double 타입과 boolean 타입의 매개변수 제공했고, 이를 받기 위하여 동일한 타입이 포함되도록 작성한 것이다.
(1)
public calss Nation {
String one = "대한민국";
(2)
Nation na = new Nation();
Nation na1 = new Nation();
//na와 na1에는 모두 "대한민국" 이 저장되어있다.
}
(1)
public class Person{
String nation = "대한민국";
String name;
String ssn;
// 나라는 동일하게 대한민국으로 설정한다.
// 이름과 주민번호는 다양하게 값을 받을 것이기에 선언만 해준다.
// 생성자
public Person(String na, String sn){
name = na;
ssn = sn;
}
}
(2)
Nation na = new Nation("감자", "020103-1357911);
Nation na1 = new Nation("고구마", "020513-4386923);
// 이 코드에서 감자 와 고구마는 매개변수 na를 통해 전달되고
// 번호는 sn을 통해 ssn에 전달된다
// 이 값들은 각각 name ssn 필드의 초기값으로 사용된다
public class Person{
String nation = "대한민국";
String name;
String ssn;
// 나라는 동일하게 대한민국으로 설정한다.
// 이름과 주민번호는 다양하게 값을 받을 것이기에 선언만 해준다.
// 생성자
public Person(String name, String ssn){
this.name = name;
this.ssn = ssn;
}
}
// this = 자기 자신의 멤버필드에 선언된 변수임을 표시해주는 것
// 자기 클래스 속 '필드'에 있는 멤버이다 를 표시해주는 것
// 생성자 속 매개변수의 변수명이 같아도 사용할 수 있게끔 해주는 그런것
매개 변수를 달리하는 생성자를 여러 개 선언하는 것을 말한다.
위와 같이 클래스의 이름은 같으면서 받는 매개 변수만 다른 것
public class Over{
Over(int num, String name){ ... }
Over(String name, int num){ ... }
// 같은 매개값이더라도 순서가 다르면 선언 가능
// Ch06_1(String number, String name){} // 가장 먼저 선언된 생성자
// Ch06_1(String number, String name){} // ←불가능
// Ch06_1(String name, String number){} // ←가능
}
생성자 오버로딩 시 주의할 점은 매개 변수의 타입과 개수 그리고 선언된 순서가 똑같을 경우, 매개변수의 이름만 바꾼다고 생성자 오버로딩이라 볼 수 없다.
Over(int num, String name){ ... }
Over(int nu, String na){ ... }
// 안된다
생성자가 오버로딩되어있을 경우, new 연산자로 생성자를 호출할 때 제공되는 매개 값의 타입과 수에 의해 호출될 생성자가 결정된다.
Ch06_1 ex3 = new Ch06_1(5.5, true);
// 호출될 생성자
// Ch06_1(double num, boolean gender){ ... }
Ch06_1 ex4 = new Ch06_1("수학과", "홍길동", false);
// 호출될 생성자
// Ch06_1(String dep, String nam, boolean gend){ ... }
// 생성자 호출 자료와 생성자 정의 매개변수 자료는 1 대 1 대응
// 생성자는 매개변수의 자료형과 갯수를 달리한다면 여러개 만들기 가능
// 생성자 오버로딩(생성자를 매개변수 타입을 다르개 해서 재사용하는 것을)
// 1개라도 명시적 생성자가 있다면 기본 생성자는 만들어지지 않는다.
클래스( 매개변수선언, ... ) {
this(매개변수, ... , 값, ...);
실행문
}
생성자 오버로딩이 많아질 경우 생성자 간 중복 코드가 발생할 수 있다. 이 경우 필드 초기화 내용은 한 생성자에 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있다.
Student(String name){
this.name = name;
this.number = 13;
this.age = 14;
}
Student(String name, int number){
this.name = name;
this.number = number;
this.age = 14;
}
Student(String name, int number, int age){
this.name = name;
this.number = number;
this.age = age;
}
한눈에 봐도 중복되는 부분이 보일 것이다. 세 개의 생성자 내용이 비슷하므로 앞 두개의 생성자에서 this()를 사용해 마지막 생성자를 호출할 수 있도록 수정하면 중복 코드를 최소화 할 수 있지 않을까
Student(String name){
this(name, 13, 14);
// 넣을 값을 넣어 마지막 생성자를 호출해 처리
}
Student(String name, int number){
this(name, number, 14);
}
Student(String name, int number, int age){
this.name = name;
this.number = number;
this.age = age;
}