본문 바로가기

Java/Java

클래스_생성자

1. 생성자

생성자는 new 연산자를 통해 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당한다.

객체 초기화는 필드를 초기화하거나, 메소드를 호출해서 객체를 사용할 준비를 하는 것이다.

 

 

2.  기본 생성자

모든 클래스는 하나 이상의 클래스를 반드시 가진다.

만약 클래스 내부에 별도의 생성자를 선언하지 않았다면, 컴파일러는 자동적으로 기본 생성자를 추가한다.

  • 기본 생성자: 클래스명() { }

그래서 생성자를 별도로 선언하지 않아도. new 연산자를 통해 기본 생성자를 호출하여 객체를 생성할 수 있다.

하지만 별도로 선언된 생성자가 하나라도 존재하면 기본 생성자는 자동적으로 추가되지 않는다.

 

 

3. 생성자 선언

생성자는 메소드와 형태가 유사하다.

하지만 리턴 타입을 명시하지 않고, 클래스명과 동일하다는 특징이 있다.

클래스는 괄호안에 매개변수를 선언할 수 있다.

매개변수는 생성자를 호출할 때 외부 값을 생성자 블록 내부로 전달하는 역할을 한다.

 

클래스에 별도의 생성자가 선언되었다면, 반드시 선언된 생성자를 호출하여 객체를 생성해야한다. 

별도의 생성자가 선언될 경우, 기본 생성자는 자동으로 추가되지 않기 때문에 사용할 수 없다.

public 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);는 기본 생성자이며, 클래스에 별도의 생성자가 명시된 경우 기본 생성자는 사용할 수 없다.

	}

}

 

 

4. 필드 초기화

필드의 초기화는 크게 세 가지 방법으로 가능하다.

  • 초기값을 선언해주지 않을 경우에는 필드가 타입에 맞는 기본값으로 초기화된다.
  • 클래스에서 필드를 선언할 때 초기값을 선언해준다.
  • 생성자의 매개변수를 통해 초기값을 할당해준다.

객체 생성 시점에서 외부에서 제공되는 다양한 값들로 초기화해야한다면, 세번째 방법인 생성자의 매개변수를 통해 초기값을 할당해줘야한다.

public class Korean {
	//필드
	String nation = "대한민국";
	String name;
	String ssn;
	
	//생성자
	public Korean(String name, String ssn) {
		//this는 객체 자신을 참조한다는 의미이다. 
		//코드의 가독성을 위해 일반적으로 생성자 매개변수와 필드의 이름을 동일하게 해주는 것이 좋다.
		//그러나 생성자 매개변수와 필드의 이름이 동일할 경우, 생성자 내부 블록에서는 필드에 접근할 수가 없다.
		//접근 우선순위가 생성자 매개변수가 더 높으며, 모든 것을 생성자 매개변수로 인식하기 때문이다.
		//이럴 경우, 필드 앞에 this를 붙여주면 필드와 매개변수를 구분할 수 있다.
		//this는 객체 자신을 참조한다는 의미를 가진다.
		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("흑수돌", "930830-9876543");
		System.out.println("k2.name: " + k2.name);
		System.out.println("k2.ssn: " + k2.ssn);
		

	}

}

위의 코드처럼 일반적으로 생성자의 매개변수는 필드와 동일한 이름을 사용한다.

그러나 생성자의 매개변수와 필드의 이름이 동일할 경우, 생성자 내부 블록에서 해당 필드에 접근할 수 없다.

생성자 내부에서는 매개변수의 사용 우선 순위가 더 높기 때문이다.

따라서 필드가 아닌 매개변수로 인식하게 된다.

 

이것을 해결하기 위해 필드와 매개변수를 구별해줄 필요가 있다. 

해결방법은 필드 앞에 this.를 붙여서 this.필드명으로 사용하는 것이다.

this는 객체 자신을 참조하라는 키워드이다. 

 

 

5. 생성자 오버로딩

외부에서 제공되는 데이터는 그 형태(타입, 개수 등)가 다양할 수 있다.

이러한 다양한 데이터에 맞게 객체를 초기화하기 위해서는 생성자도 다양해져야한다. 

그래서 자바는 생성자 오버로딩을 제공한다.

생성자 오버로딩이란 매개변수의 타입, 개수, 순서.. 즉 매개변수를 달리하는 생성자를 여러개 선언하는 것이다.

 

생성자 오버로딩할 때 주의할 점이 있다.

매개변수의 타입, 개수, 순서가 동일하고 매개변수 이름만 달리하는 것은 생성자 오버로딩이 아니라는 것이다.

 

생성자가 오버로딩되어 있을 경우, 호출할 생성자를 결정하는 기준은 매개변수의 타입과 개수이다.

public class Car {
	//필드
	String company = "현대자동차";
	String model;
	String color;
	int maxSpeed;
	
	//생성자(오버로딩)
	Car() {
		
	}
	
	Car(String model) {
		this.model = model;
	}
	
	Car(String model, String color) {
		this.model = model;
		this.color = color;
	}
	
	Car(String model, String color, int maxSpeed) {
		this.model = model;
		this.color = color;
		this.maxSpeed = maxSpeed;
	}

}

 

public class CarExample {

	public static void main(String[] args) {
		Car car1 = new Car(); //기본생성자 사용
		System.out.println("car1.company: " + car1.company);
		System.out.println();
		
		Car car2 = new Car("자가용"); //두번째 생성자 사용
		System.out.println("car2.company: " + car2.company);
		System.out.println("car2.model: " + car2.model);
		System.out.println();
		
		Car car3 = new Car("자가용", "빨강"); //세번째 생성자 사용
		System.out.println("car3.company: " + car3.company);
		System.out.println("car3.model: " + car3.model);
		System.out.println("car3.color: " + car3.color);
		System.out.println();
		
		Car car4 = new Car("자가용", "빨강", 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();
		

	}

}

 

 

6. 다른 생성자 호출: this()

생성자 오버로딩이 많아질 수록, 생성자간에 중복된 코드가 많아질 수 있다. 

이런 상황은 비효율적이며 가독성이 좋지 못하다.

 

이런 상황은 필드 초기화 내용을 가장 포괄적인 한 생성자에 집중적으로 작성하고, 

나머지 생성자가 그 포괄적인 생성자를 호출하는 방식으로 코드를 작성하여 개선할 수 있다.

 

이때 사용되는 키워드가  this( ... )이다.

this( ... )는 객체 자신의 다른 생성자를 호출하는 코드이다.

this( ... )는 반드시 사용되는 생성자 내부에서 첫줄에 작성되어야한다.

호출할 생성자는 매개변수 타입, 개수에 의해 결정된다.

아래의 코드에서 세번째 생성자가 가장 포괄적인 생성자이며, 

첫번째, 두번째 생성자는 this( ... )를 통해 세번째 생성자를 호출한다.

public class Car {
	//필드
	String company = "현대자동차";
	String model;
	String color;
	int maxSpeed;
	
	//생성자
	Car() {
		
	}
	
	Car(String model) {
		this(model, "빨강", 250);
	}
	
	Car(String model, String color) {
		this(model, color, 250);
	}
	
	Car(String model, String color, int maxSpeed) {
		this.model = model;
		this.color = color;
		this.maxSpeed = maxSpeed;
	}

}

 

import sec03.exam04.Car;

public class CarExample {

	public static void main(String[] args) {
		Car car1 = new Car(); 
		System.out.println("car1.company: " + car1.company);
		System.out.println();
		
		Car car2 = new Car("자가용");
		System.out.println("car2.company: " + car2.company);
		System.out.println("car2.model: " + car2.model);
		System.out.println("car2.color: " + car2.color);
		System.out.println("car2.maxSpeed: " + car2.maxSpeed);
		System.out.println();
		
		Car car3 = new Car("자가용", "빨강"); 
		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.maxSpeed: " + car3.maxSpeed);
		System.out.println();
		
		Car car4 = new Car("자가용", "빨강", 200);
		System.out.println("car2.company: " + car4.company);
		System.out.println("car2.model: " + car4.model);
		System.out.println("car2.color: " + car4.color);
		System.out.println("car2.maxSpeed: " + car4.maxSpeed);
		System.out.println();
		
	}

}

 

 

출처: 혼자 공부하는 자바(신용권)

'Java > Java' 카테고리의 다른 글

클래스_인스턴스 멤버와 정적멤버  (0) 2021.11.28
클래스_메소드  (0) 2021.11.14
클래스_필드  (0) 2021.11.14
클래스_객체 지향 프로그래밍  (0) 2021.11.12
배열  (0) 2021.10.12