혼공자바] 06-3 생성자
06-3 / 생성자
- 생성자의 정의
생성자는 new 연산자로 클래스로투버 객체를 생성할 때 호출되어 객체의 초기화를 담당한다. 객체 초기화란 필드를 초기화하거나 메소드를 호출해 객체를 사용할 준비를 하는 것을 말한다. new 연산자에 의해 생성자가 성공적으로 실행되면 힙 영역에 객체가 생성되고 객체의 번지가 리턴된다. 리턴된 객체 번지는 클래스 변수에 저장된다.
기본 생성자)
모든 클래스는 생성자가 반드시 존재하며 하나 이상 가질 수 있다. 만약 생성자 선언을 생략했다면 컴파일러는 다음과 같이 기본 생성자를 바이트 코드에 자동 추가한다.
public class Main {
public Main(){ } // 기본 생성자 자동 추가
}
그래서 클래스에 생성자를 선언하지 않아도 new 연산자 뒤에 기본 생성자를 호출해서 객체를 생성할 수 있다.
만약 클래스에 명시적으로 선언한 생성자가 1개라도 있다면 기본 생성자를 추가하지 않는다. 그런데 따로 명시적으로 생성자를 선언하는 이유는 다양한 값으로 초기화하기 위해서이다.
생성자 선언)
클래스이름과 동일한이름 (매개변수, ... ) {
} // 생성자 블록
생성자는 메소드와 비슷한 모양잊만 리턴 타입이 없고, 클래스 이름과 동일하다.
매개변수 선언은 생략할 수도 있고 여러개를 선언할 수도 있다. 매개변수는 new연산자로 생성자를 호출할 때 외부값을 생성자 블록 내부로 전달하는 역할을 한다.
만약 클래스에 명시적으로 선언된 생성자에 매개변수가 있다면 기본 생성자로 호출해서 객체를 생성할 수 없고 매개변수를 포함해 호출해야 객체를 생성해야 한다.
public class Car{
Car(String model, String color, int maxSpeed){...}
}
// new Car(); - X
// new Car(casfer, kaki, 100); - O
필드 초기화)
객체가 생성될 때 필드는 기본 초기값으로 자동설정.
다른 값을 주고 싶다면, 필드 선언할때 초기값을 따로 주는 방법, 또는 생성자에서 초기값을 주는 방법이다.
- 초기값을 준 경우
public class Korean {
String nation = "대한민국";
String name;
String ssn;
}
nation이라는 필드에 대한민국이라는 초기값을 선언했다. 이는 Korean클래스로 부터 객체를 생성될 때 마다 동일하게 적용된다.
- 객체 생성시 생성자에서 초기화 하며 초기값을 주는 경우
public class Korean {
String nation = "대한민국";
String name;
String ssn;
public Korean (String name, String ssn){
this.name = name; // this.필드 = 매개변수
this.ssn = ssn;
}
}
매개변수 일름은 헷갈리지 않게 사용될 필드와 비슷하게 또는 동일하게 사용하는 것이 좋다.
하지만 매개변수와 필드 이름이 동일하다면 생성자 내부에서 해당 필드에 접근 할 수 없다. 동일한 이름일 경우 우선순위는 매개 변수가 더 높기 때문. 이럴때 필드에 접근하기 위해 this를 붙이게 된다. 이 this는 객체 자신을 의미한다.
생성자에서 초기화를 할때는 중요한 몇개 필드만 매개 변수를 통해 초기화되고 나머지 필드는 선언시에 초기화 하거나 생성자 내부에서 임의의 값 또는 계산 된 값으로 초기화 한다.
생성자 오버로딩)
외부로 부터의 다양한 데이터들을 이용하기 위해 객체를 초기화 하려면 생성자도 다양해야 할 필요가 있다.
여러가지 요구 조건을 수용할 수 있는 다양한 객체를 만들기 위해 자바에서는 생성자 오버로딩(Overloading)을 제공한다.
이는 매개변수를 달리하는 생성자를 여럿 선언하는 것을 말한다.
public class Car{
Car(){...}
Car(String model){...}
Car(String model, String color){...}
Car(String model, String color, int maxSpeed){...}
}
주의) 매개변수의 타입과 개수 그리고 순서가 동일하다면 변수이름을 바꾼다고 생성자 오버로딩이 되는 것은 아니다. 결국 동일한 생성자.
Car(String model, String color){...}
Car(String color, String model){...}
// 타입, 개수, 순서도 다를거 없어서 결국 동일
다른 생성자 호출: this() )
생성자는 또다른 생성자를 호출할 수도 있다.
필드 초기화 내용은 한 생성자에만 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지는 방법으로도 사용할 수 있다.
this()는 자신의 다른 생성자를 호출하는 코드는 반드시 생성자의 첫 줄에서만 허용된다.
this()의 매개값은 호출되는 생성자의 매개 변수에 맞게 제공해야한다. this()로 호출된 생성자 실행이 끝나면 다시 원래 생성자로 돌아와 다음 실행문을 진행한다.
// Car.java
public class Car {
String company = "현대자동차";
String model;
String color;
int maxSpeed;
Car(){
model = "casfer";
color = "kaki";
maxSpeed = 100;
}
Car(String model){
this();
this.model = model;
}
Car(String model, String color){
this();
this.model = model;
this.color = color;
}
Car(String model, String color, int maxSpeed){
this();
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
}
}
// CarExample.java
public class CarExample {
public static void main(String[] args){
Car car1 = new Car();
System.out.println(car1.company);
System.out.println(car1.model);
System.out.println(car1.color);
System.out.println(car1.maxSpeed);
System.out.println("----------------------------");
Car car2 = new Car("avante");
System.out.println(car2.model);
System.out.println("----------------------------");
Car car3 = new Car("sonata","black");
System.out.println(car3.model);
System.out.println(car3.color);
System.out.println("----------------------------");
Car car4 = new Car("tucson","navy",130);
System.out.println(car4.model);
System.out.println(car4.color);
System.out.println(car4.maxSpeed);
}
}
- 출력결과