For Programmer

6-2 클래스 - 생성자 본문

Programming language/Java

6-2 클래스 - 생성자

유지광이 2021. 8. 13. 01:04
728x90

생성자는 클래스로부터 객체가 생성될 때 객체의 초기화 과정을 기술하는 특수한 메소드이며 객체가 생설될 때 무조건 수행된다.

[public/private/protected] 클래스 이름(매개 변수) {
    // 초기화 문장들
}

 

생성자(Constructor)는 new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당한다. 

인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다.

new 연산자에 의해 생성자가 성공적으로 실행되면 힙(Heap) 영역에 객체가 생성되고 객체의 주소가 리턴된다.

리턴된 객체의 주소는 클래스 타입 변수에 저장되어 객체에 접근할 때 이용된다.

 

생성자의 이름은 클래스의 이름과 같아야 한다.

- 생성자는 리턴 값이 없다.

- 생성자도 오버로딩이 가능하므로 하나의 클래스에 여러 개의 생성자가 있을 수 있다.

- 생성자도 메서드이기 때문에 리턴값이 없다는 의미의 void를 적어야 하지만, 모든 생성자가 리턴값이 없으므로 void를 생략하도록 한 것이다.

 

ClassName c = new ClassName();

연산자 new에 의해서 메모리(heap)에 ClassName 클래스의 인스턴스가 생성된다

생성자 ClassName()가 호출되어 수행된다.

연산자 new의 결과로, 생성된 ClassName 인스턴스의 주소가 반환되어 참조변수 c에 저장된다.

 

지금까지 인스턴스를 생성하기 위해 사용해왔던 '클래스이름()'이 바로 생성자였던 것이다.

인스턴스를 생성할 때는 반드시 클래스 내에 정의된 생성자 중의 하나를 선택하여 지정해주어야 한다.

 

기본 생성자

모든 클래스는 생성자가 반드시 존재하며, 하나 이상을 가질 수 있다.

우리가 클래스 내부에 생성자 선언을 생략했다면 컴파일러는 기본 생성자(default constructor)를 바이트 코드에 자동 추가시킨다.

ClassName() {}

컴파일러가 자동적으로 추가해주는 기본 생성자는 이와 같이 매개 변수도 없고 아무런 내용도 없는 아주 간단한 것이다.

 

주의할 점은 컴파일러가 자동적으로 기본 생성자를 추가해주는 경우는 클래스에 정의된 생성자가 하나도 없을 때 뿐이다.

생성자가 하나라도 있다면, 컴파일러는 기본 생성자를 추가하지 않는다.

 

2. 매개 변수가 있는 생성자

생성자는 메소드와 비슷한 모양을 가지고 있으나, 리턴 타입이 없고 클래스 이름과 동일해야 한다.

생성자도 메소드처럼 매개변수를 선언하여 호출 시 값을 넘겨받아 인스턴스의 초기화에 사용할 수 있다.

인스턴스마다 각기 다른 값으로 초기화되어야하는 경우가 많기 때문에 매개 변수를 사용한 초기화는 매우 유용하다.

 

class Car {
    String color;        // 색상
    String gearType;    // 변속기 종류 - auto(자동), manual(수동)
    int door;            // 문의 개수
 
    Car() {} // 기본 생성자
    Car(String c, String g, int d) { //사용자 정의 생성자
        color = c;
        gearType = g;
        door = d;
    }
}

 

위와 같이 초기화 할 경우 매개 변수의 이름들이 너무 짧아 코드의 가독성이 떨어지는 경우가 많다.

그래서 여기서 this 키워드를 사용하여 가독성 문제를 해결할 수 있다.

this는 객체 자기 자신의 참조 주소 값을 가지고 있다.

this를 통해 필드와 동일한 이름을 갖는 매개 변수를 사용할 수 있다.

 

class Car {
    String color;        // 색상
    String gearType;    // 변속기 종류 - auto(자동), manual(수동)
    int door;            // 문의 개수
 
    Car() {}
    Car(String color, String gearType, int door) {
        this.color = c;
        this.gearType = g;
        this.door = d;
    }
}

 

3.생성자 오버로딩(Constructor overloading)

외부의 다양한 데이터를 이용해 객체를 초기화하려면 생성자도 다양화될 필요가 있다.

생성자 오버로딩을 통해 매개 변수를 달리하여 생성자를 여러 개 선언하여 다양화할 수 있다.

 

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

접근 제어 제한자(Access Control Modifiers)

  • Visible to the class only (private).
  • Visible to the world (public)

4. 생성자에서 다른 생성자 호출

생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있다. 

매개 변수의 수만 달리하고 필드 초기화 내용이 비슷한 생성자에서 이러한 현상을 많이 볼 수 있다.

필드 초기화 내용은 한 생성자에만 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있다.

생성자에서 다른 생성자를 호출할 때에는 this() 코드를 사용한다.

그리고 이 this() 호출은 반드시 생성자의 첫 줄에서만 호출이 가능하다.

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


5. 생성자를 이용한 인스턴스 복사

현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있다.

두 인스턴스가 같은 상태를 갖는다는 것은 두 인스턴스의 모든 인스턴스 변수가 동일한 값을 갖고 있다는 것을 뜻한다.

하나의 클래스로부터 생성된 모든 인스턴스의 메소드와 클래스 변수는 서로 동일하기 때문에 인스턴스 간의 차이는 인스턴스마다 각기 다른 값을 가질 수 있는 인스턴스 변수이다.

class Car {
    String color;        // 색상
    String gearType;    // 변속기 종류 - auto(자동), manual(수동)
    int door;            // 문의 개수
 
    Car() {
        this("white", "auto", 4);
    }
 
    Car(Car c) {    // 인스턴스의 복사를 위한 생성자.
        color = c.color;
        gearType = c.gearType;
        door = c.door;
    }
 
    Car(String color, String gearType, int door) {
        this.color = color;
        this.gearType = gearType;
        this.door = door;
    }
}
class CarTest3 {
    public static void main(String[] args) {
        Car c1 = new Car();
        Car c2 = new Car(c1);    // c1의 복사본 c2를 생성한다.
        System.out.println("c1의 color=" + c1.color + ", gearType=" + c1.gearType+ ", door="+c1.door);
        System.out.println("c2의 color=" + c2.color + ", gearType=" + c2.gearType+ ", door="+c2.door);
 
        c1.door=100;    // c1의 인스턴스변수 door의 값을 변경한다.
        System.out.println("c1.door=100; 수행 후");
        System.out.println("c1의 color=" + c1.color + ", gearType=" + c1.gearType+ ", door="+c1.door);
        System.out.println("c2의 color=" + c2.color + ", gearType=" + c2.gearType+ ", door="+c2.door);
    }
}

인스턴스 c2는 c1을 복사하여 생성된 것이므로 서로 같은 상태를 갖지만, 서로 독립적으로 메모리 공간에 존재하는 별도의 인스턴스이므로 c1의 값들이 변경되어도 c2는 영향을 받지 않는다.

 

 

출처:https://programmer-seva.tistory.com/79

728x90

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

6-3 클래스 - 메소드  (0) 2021.08.13
6-1. 클래스 - 멤버 변수  (0) 2021.08.13
6. 클래스  (0) 2021.08.13
5. 제어문(가정문,반복문)  (0) 2021.08.12
4. 배열  (0) 2021.08.11
Comments