Programming/Java

혼공자바] 06-3 생성자

littlezero48 2022. 11. 24. 20:41

 

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);
    }
}

- 출력결과