JAVA 생성자
생성자는 new 연산자로 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당합니다.
객체 초기화란 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 하는 것을 말합니다. 생성자를 실행하지 않고는 클래스로부터 객체를 만들 수 없습니다. new 연산자에 의해 생성자가 성공적으로 실행되면 힙 영역에 객체가 생성되고 객체의 번지가 리턴됩니다. 리턴된 객체는 클래스 변수에 저장됩니다.
기본생성자
모든 클래스는 생성자가 반드시 존재하며, 생성자를 하나 이상 가질 수 있습니다. 우리가 클래스 내부에 생성자 선언을 생략했지만 컴파일러는 중괄호 블록{]내용이 비어 있는 기본 생성자를 바이트 코드에 자동 추가합니다.
[public] 클래스() {}
클래스가 public class 로선언되면 기본 생성자에도 public이 붙지만 public없이 class로만 선언되면 기본 생성자에도 pubilc이 붙지 않습니다.
생성자 선언
기본 생성자 대신 우리가 생성자를 명시적으로 선언하려면 다음과 같은 형태로 작성하면 됩니다.
클래스 ( 매개변수선언, ···) { //{}안은 생성자 블록
// 객체의 초기화 코드
}
생성자 선언
package ch06;
public class Car2 {
// 생성자
Car2(String color, int cc){
}
}
생성자를 호출해서 객체 생성
package ch06;
public class Car2Exmaple {
public static void main(String[] args) {
// TODO Auto-generated method stub
Car2 myCar = new Car2("검정",3000);
// Car2 myCar = new Car(); (x) 기본생성자를 호출할 수 없다
}
}
클래스에 생성자가 명시적으로 선언 되어 있을 경우에는 반드시 생성자를 호출해서 객체를 생성해야만 합니다.
필드 초기화
클래스로부터 객체가 생성될 때 필드는 기본 초기값으로 자동 설정됩니다. 다른 값으로 초기화 하고 싶다면 두 가지 방법이 있습니다.
- 필드를 선언할 때 초기값을 설정한다.
- 생성자에서 초기값을 준다
필드를 선언할 때 초기값을 주게 되면 동일한 클래스로부터 생성되는 객체들은 모두 같은 값을 가지게 됩니다. 객체 생성 후 초기값을 변경해도 되지만, 객체 생성 시점에는 필드의 값이 모두 같습니다.
예)
public class Korean{ Korean k1 = new korean();
String nation = "대한민국"; Korean k2 = new korean();
String name;
String ssn;
}
Korean 클래스로 부터 k1과 k2 객체를 생성하면 k1과 k2 의 nation 필드에는 모두 "대한민국"이 저장되어 있습니다.
하지만 객체 생성 시점에서 외부에서 제공되는 다양한 값들로 초기화 되어야한다면 생성자에서 초기화 해야합니다.
public class Korean{ public korean(String n, String s){
String nation = "대한민국"; name = n;
String name; ssn = s;
String ssn; }
} }
korean k1 = new Korean("박자바","011225-1234567");
korean k2 = new Korean("김자바","930525-0564321");
위 코드에서 "박자바","김자바"는 매개변수 n을 통해 전달되고 "011225- 1234567",930525-0564321"은 매개 변수 s를 통해 전달됩니다. 이 값들은 각각 name 필드와 ssn필드의 초기값으로 사용됩니다.
생성자에서 필드 초기화
package ch06;
public class Korean {
// 필드
String nation = "대한민국";
String name;
String ssn;
// 생성자
public Korean(String n,String s) {
name = n;
ssn = s;
}
}
객체 생성 후 필드 값 출력
package ch06;
public class KoreanExample {
public static void main(String[] args) {
// TODO Auto-generated method stub
Korean k1 = new Korean("박자바","011225-1234567");
System.out.println("k1.name : "+ k1.name);
System.out.println("k1.ssn : "+ k1.ssn);
Korean k2 = new Korean("김자바","930525-0564321");
System.out.println("k2.name : "+ k2.name);
System.out.println("k2.ssn : "+ k2.ssn);
}
}
Korean 생성자의 매개변수 값은 n과 s를 사용했지만 매개변수의 이름이 짧으면 가독성이 좋지 않기 때문에 가능하면 초기화시킬 필드의 이름과 비슷하거나 동일하게 해주는 것이 좋습니다. 하지만 이름이 동일할 경우 매개 변수가 우선사용순위가 높아 필드에 접근할수 없기 때문에 필드에 이름앞에 this 를 사용해주는것이 좋습니다.
예)
public Korean (String name, String ssn){
this.name = name;
thiss.ssn = ssn;
객체의 필드는 하나가 아니라 여러 개가 있고, 이 필드들을 모두 생성자에 초기화한다면 생성자의 매개변수 수는 객체의 필드 수만큼 선언되어야 합니다. 그러나 실제로는 중요한 몇개의 필드만 매개 변수를 통해 초기화 되고 나머지 필드들은 필드 선언 시에 초기화 하거나 생성자 내부에서 임의의 값 또는 계산된 값으로 초기화 합니다. 아니면 객체 생성 후에 필드값을 별도로 저장하기도 합니다.
생성자 오버로딩
외부에서 제공되는 다양한 데이터들을 이용해서 객체를 초기화 하려면 생성자도 다양화될 필요가 있다.
Car 객체를 생성할 때 외부에서 제공되는 데이터가 없다면 기본 생성자로 Car객체를 생성하고 외부에서 model데이터가 제공되거나 model과 color가 제공될 경우에도 Car 객체를 생성할수 있어야 한다면 다양한 방법으로 객체를 생성할 수 있도록 생성자 오버로딩을 제공합니다. 매개 변수를 달리하는 생성자를 여러 개 선언하는것을 생성자 오버로딩이라고 합니다.
public class 클래스 {
클래스 ([타입 매개변수, ···]){
···
}
클래스 ([타입 매개변수, ···]){
···
}
}
예)
public class Car {
Car() { ··· }
Car(String model) { ··· }
Car(String model, String color) { ··· }
Car(String model, String color, int maxSpeed) { ··· }
}
Car 객체 생성
Car car1 = new Car();
Car car2 = new Car("그랜저");
Car car3 = new Car("그랜저","흰색");
Car car4 = new Car("그랜저","흰색","300");
오버로딩 시 주의할 점
매개변수의 타입과 개수 그리고 선언된 순서가 똑같을 경우 순서와 이름만 바꾸는건 오버로딩이 아닙니다.
생성자의 오버로딩
package ch06;
public class Car3 {
// 필드
String company = "현대자동차";
String model;
String color;
int maxSpeed;
// 생성자
Car3(){
}
Car3(String model){
this.model = model;
}
Car3(String model,String color){
this.model = model;
this.color = color;
}
Car3(String model,String color,int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
}
}
객체 생성시 생성자 선택
package ch06;
public class Car3Example {
public static void main(String[] args) {
// TODO Auto-generated method stub
Car3 car1 = new Car3();
System.out.println("car1.company:"+car1.company);
System.out.println();
Car3 car2 = new Car3("자가용");
System.out.println("car2.company:"+car2.company);
System.out.println("car2.model:"+car2.model);
System.out.println();
Car3 car3 = new Car3("자가용","빨강");
System.out.println("car3.company:"+car3.company);
System.out.println("car3.model:"+car3.model);
System.out.println("car3.color:"+car3.color);
System.out.println();
Car3 car4 = new Car4("택시","검정",200);
System.out.println("car4.company:"+car4.company);
System.out.println("car4.model:"+car4.model);
System.out.println("car4.color:"+car4.color);
System.out.println("car4.maxSpeed:"+car4.maxSpeed);
}
}
다른 생성자 호출:this()
생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있습니다. 매개 변수의 수만 달리하고 필드 초기화 내용이 비슷한 생성자에서 이러한 현상을 많이 볼 수 있습니다. 이 경우에는 필드 초기화 내용은 한 생성자에만 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있습니다.
클래스( [매개변수, ···] ) {
this ( 매개변수, ···, 값, ··· ) ; ←클래스의 다른 생성자 호출
실행문;
}
this()는 자신의 다른 생성자를 호출하는 코드로 반드시 생성자의 첫 줄에서만 허용됩니다. this()의 매개값은 호출되는 생성자의 매개 변수에 맞게 제공해야 합니다. this() 다음에는 추가적인 실행문들이 올 수 있습니다. 이 말은 호출되는 생성자의 실행이 끝나면 원래 생성자로 돌아와서 다음 실행문을 진행한다는 뜻입니다.
다른 생성자를 호출해서 중복 코드 줄이기
package ch06;
public class Car4 {
// 필드
String company = "현대자동차";
String model;
String color;
int maxSpeed;
// 생성자
Car4(){
}
Car4(String model){
this(model,"은색",250); // 호출
}
Car4(String model,String color){
this(model, color ,250); // 호출
}
Car4(String model,String color,int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed; // 공통 실행 코드
}
}
객체 생성 시 생성자 선택
package ch06;
public class Car4Example {
public static void main(String[] args) {
// TODO Auto-generated method stub
Car4 car1 = new Car4();
System.out.println("car1.company:"+ car1.company);
System.out.println();
Car4 car2 = new Car4("자가용");
System.out.println("car2.company:" + car2.company);
System.out.println("car2.model:" + car2.model);
System.out.println();
Car4 car3 = new Car4("자가용","빨강");
System.out.println("car3.company:" + car3.company);
System.out.println("car3.model:" + car3.model);
System.out.println("car3.color:" + car3.color);
System.out.println();
Car4 car4 = new Car4("택시","검정",200);
System.out.println("car4.company:" + car4.company);
System.out.println("car4.model:" + car4.model);
System.out.println("car4.color:" + car4.color);
System.out.println("car4.maxSpeed:" + car4.maxSpeed);
}
}