[Java]생성자

Devlog·2024년 3월 6일

Java

목록 보기
13/41

✔ 생성자(Constructor)

- new 연산자로 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당
- 객체 초기화: 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 하는 것
- 생성자를 실행하지 않고는 클래스로부터 객체를 만들 수 없음
- new 연산자에 의해 생성자가 성공적으로 실행되면
  힙(heap)영역에 객체가 생성되고 객체의 번지가 리턴됨


✔ 기본 생성자

- 모든 클래스는 생성자가 반드시 존재하며, 생성자를 하나 이상 가질 수 있음
- 클래스 내부에 생성자 선언을 생략했다면
  컴파일러는 [public] 클래스() { } 기본 생성자를 바이트 코드에 자동 추가
- 클래스가 public class로 선언되면 기본 생성자에도 public이 붙지만,
  클래스가 public 없이 class로만 선언되면 기본 생성자에도 public이 붙지 않음

∴ 클래스에 생성자를 선언하지 않아도
   new 연산자 뒤에 기본 생성자를 호출해서 객체를 생성할 수 있음

ex) Car myCar = new Car();

- 클래스에 명시적으로 선언한 생성자가 1개라도 있으면
  컴파일러는 기본 생성자를 추가하지 않음
→ 명시적으로 생성자를 선언하는 이유는
  객체를 다양한 값으로 초기화하기 위해서임


✔ 생성자 선언

// 생성자 블록
클래스( 매개변수선언, ··· ) {
    // 객체의 초기화 코드
}

- 리턴 타입이 없고 클래스 이름과 동일함
- 생성자 블록 내부에는 객체 초기화 코드가 작성됨
 일반적으로 필드에 초기값을 저장하거나 메소드를 호출하여
 객체 사용 전에 필요한 준비를함
- 매개 변수 선언은 생략할 수도 있고 여러 개를 선언해도 됨

Car myCar = new Car("그랜저", "검정", 300);

public class Car {
	//생성자
    Car(String model, String color, int maxSpeed) { ... }
}

→ 클래스에 생성자가 명시적으로 선언되어 있을 경우에는 반드시 선언된 생성자를 호출해서 객체를 생성해야만함

// Car클래스에 생성자 선언이 있기 때문에
// 기본 생성자(Car())를 호출해서 객체를 생성할 수 없고
// Car(String color, int cc)를 호출해서 객체를 생성해야함
class Car {
	//생성자
	Car(String color, int cc){
	}
}

public class CarExample { 
	public static void main(String[] args {
		Car myCar = new Car("검정", 3000);
		//Car myCar = new Car(); <- 기본 생성자를 호출할 수 없음
	}
}

✔ 필드 초기화

- 클래스로부터 객체가 생성될 때 필드는 기본 초기값으로 자동 설정됨
- 필드를 선언할 때 초기값을 주게 되면
  동일한 클래스로부터 생성되는 객체들은 모두 같은 값을 갖게 됨

- 초기화 하는 방법
1) 필드를 선언할 때 초기값을 주는 방법
2) 생성자에서 초기값을 주는 방법

→ 객체 생성 시점에 외부에서 제공되는 다양한 값들로 초기화되어야 한다면
  생성자에서 초기화 해야함. 생성자의 매개값으로 이 값들을 받아 초기화해야함

👩‍💻생성자에서 필드 초기화 및 객체 생성 후 필드값 출력
class Korean{
	//필드
	String nation = "대한민국";
	String name;
	String ssn;
	
	//생성자
	public Korean(String n, String s) {
		name = n;
		ssn = s;
	}
	
	/*
	 * 필드와 매개 변수 이름이 동일하기 때문에 생성자 내부에서 해당 필드에 할 수 없음
	 * -> 동일한 이름의 매개 변수가 사용 우선순위가 높기 때문
	 * 해결방법
	 * 필드 앞에 'this.'를 붙이면 됨
	 * this는 객체 자신의 참조
	 * this라는 참조 변수로 필드를 사용하는 것과 동일함
	 */
	
	/*
	 * public Korean(String name, String ssn) {
	 * 	this.name(필드) = name(매개변수);
	 * 	this.ssn(필드) = ssn(매개변수);
	 * }
	 */
}

public class KoreanExample {
	public static void main(String[] args) {
		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-0654321");
		System.out.println("k2.name : " + k2.name);
		System.out.println("k2.ssn : " + k2.ssn);
	}
}

💻결과
k1.name : 박자바
k1.ssn : 011225-1234567
k2.name : 김자바
k2.ssn : 930525-0654321

- 필드들을 모두 생성자에서 초기화한다면
  생성자의 매개 변수 수는 객체의 필드 수만큼 선언되어야 함
- 보통은 중요한 몇 개의 필드만 매개 변수를 통해 초기화 되고,
  나머지 필드들은 필드 선언 시에 초기화하거나
  생성자 내부에서 임의의 값 또는 계산된 값으로 초기화

  아니면 객체 생성 후에 필드값을 별도로 저장하기도 함


✔ 생성자 오버로딩

- 매개 변수를 달리하는 생성자를 여러 개 선언하는 것
- 다양한 방법으로 객체를 생성할 수 있음

public class 클래스 {
	// [생성자의 오버로딩] 매개 변수의 타입, 개수, 순서가 다르게 선언
	클래스 ( [타입 매개변수, ···] ) {
		...
	}
	
	클래스 ( [타입 매개변수, ···] ) {
		...
	}
}

ex)
▶ Car 클래스에서 생성자 오버로딩
public class Car {
Car() {...}
Car(String model) { ... }
Car(String model, String color) { ... }
Car(String model, String color, int maxSpeed) { ... }
}

▶ 객체 생성
Car car1 = new Car();
Car car2 = new Car("그랜저");
Car car3 = new Car("그랜저", "흰색");
Car car4 = new Car("그랜저", "흰색", 300);

* 주의할 점
: 매개 변수의 타입과 개수 그리고 선언된 순서가 똑같을 경우
  매개 변수 이름만 바꾸는 것은 생성자 오버로딩이 아님
ex)
Car(String model, String color) { ... }
Car(String color, String model) { ... }

👩‍💻 생성자의 오버로딩 및 객체 생성 시 생성자 선택
class Car2{
	//필드
	String company = "현대자동차";
	String model;
	String color;
	int maxSpeed;
	
	//생성자
	//생성자1
	Car2(){
		
	}
	
	//생성자2
	Car2(String model) {
		this.model = model;
	}
	
	//생성자3
	Car2(String model, String color){
		this.model = model;
		this.color = color;
	}
	
	//생성자4
	Car2(String model, String color, int maxSpeed){
		this.model = model;
		this.color = color;
		this.maxSpeed = maxSpeed;
	}
	
}

public class CarExample2 {
	public static void main(String[] args) {
		//생성자1 선택
		Car2 car1 = new Car2();
		System.out.println("car1.company: " + car1.company);
		System.out.println();
		
		//생성자2 선택
		Car2 car2 = new Car2("자가용");
		System.out.println("car2.company: " + car2.company);
		System.out.println("car2.model: " + car2.model);
		System.out.println();
		
		//생성자3 선택
		Car2 car3 = new Car2("자가용", "빨강");
		System.out.println("car3.company: " + car3.company);
		System.out.println("car3.model: " + car3.model);
		System.out.println("car3.color: " + car3.color);
		System.out.println();
		
		//생성자4 선택
		Car2 car4 = new Car2("자가용", "빨강", 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);
		System.out.println();
	}
}

💻출력
car1.company: 현대자동차

car2.company: 현대자동차
car2.model: 자가용

car3.company: 현대자동차
car3.model: 자가용
car3.color: 빨강

car4.company: 현대자동차
car4.model: 자가용
car4.color: 빨강
car4.maxSpeed: 200

✔ 다른 생성자 호출: this()

[표현법]
클래스( [매개변수, ···] ) {
   this( 매개변수, ···, 값, ···); //클래스의 다른 생성자 호출
   실행문;
}

- 생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있음
  → 이 경우에는 필드 초기화 내용은 한 생성자에만 집중적으로 작성하고
    나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선

- 자신의 다른 생성자를 호출하는 코드로 반드시 생성자의 첫 줄에서만 허용
- this()의 매개값은 호출되는 생성자의 매개 변수에 맞게 제공해야 함

👩‍💻 다른 생성자를 호출해서 중복 코드 줄이기 및 객체 생성 시 생성자 선택
class Car3{
	//필드
	String company = "현대자동차";
	String model;
	String color;
	int maxSpeed;
	
	//생성자
	Car3(){
		
	}
	
	// this()를 사용해서 마지막 생성자인 
    // Car3(String model, String color, int maxSpeed)를 호출하도록 함
	Car3(String model) {
		this(model, "은색", 250);
	}
	
	Car3(String model, String color){
		this(model, color, 250);
	}
	
	Car3(String model, String color, int maxSpeed){
		// this(model, "은색", 250); 호출
		// this(model, color, 250); 호출
		this.model = model;
		this.color = color;
		this.maxSpeed = maxSpeed;
	}
	
}

public class CarExample3 {
	public static void main(String[] args) {
		//생성자1 선택
		Car3 car1 = new Car3();
		System.out.println("car1.company: " + car1.company);
		System.out.println();
		
		//생성자2 선택
		Car3 car2 = new Car3("자가용");
		System.out.println("car2.company: " + car2.company);
		System.out.println("car2.model: " + car2.model);
		System.out.println();
		
		//생성자3 선택
		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();
		
		//생성자4 선택
		Car3 car4 = new Car3("자가용", "빨강", 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);
		System.out.println();
	}
}

💻출력
car1.company: 현대자동차

car2.company: 현대자동차
car2.model: 자가용

car3.company: 현대자동차
car3.model: 자가용
car3.color: 빨강

car4.company: 현대자동차
car4.model: 자가용
car4.color: 빨강
car4.maxSpeed: 200

0개의 댓글