3 minute read

Updated:

생성자

  • 인스턴스가 생성될 때 호출되는 ‘인스턴스 초기화 메서드’
  • 인스턴스 변수의 초기화 작업에 주로 사용된다.

생성자의 조건

  1. 생성자의 이름은 클래스의 이름과 같아야 한다.
  2. 생성자는 리턴값이 없다.
  • 연산자 new가 인스턴스를 생성하는 것이지 생성자가 인스턴스를 생성하는 것이 아니다.
class Card {
    Card () {   // 매개변수가 없는 생성자
        ...
    }
    
    Card (String k, int num) {   // 매개변수가 있는 생성자
        ...
    }
}
Card c = new Card();

1. 연산자 new에 의해서 메모리(heap) Car클래스의 인스턴스가 생성된다.
2. 생성자 Card() 호출되어 수행된다.
3. 연산자 new의 결과로, 생성된 Card인스턴스의 주소가 반환되어 참조변수 c에 저장된다.

기본 생성자

  • 클래스에 생성자가 하나도 정의되있지 않은 경우 컴파일러는 자동적으로 기본 생성자를 추가하여 컴파일한다.
  • 클래스에 정의된 생성자가 하나라도 있는 경우, 기본 생성자는 자동 추가되지 않으므로 기본 생성자를 추가해주던가 인스턴스를 생성할 때 정의한 생성자를 사용해야 한다.
Data1 d1 = new Data1();
Data2 d2 = new Data2();   // 에러

Data1 d1 = new Data1();
Data2 d2 = new Data2(10);   // OK

매개변수가 있는 생성자

  • 생성자도 메서드처럼 매개변수를 선언하여 호출 시 값을 넘겨받아서 인스턴스의 초기화 작업에 사용할 수 있다.
  • 이떄, 매개변수를 갖는 생성자를 사용하면 코드가 보다 간결하고 직관적이다.
  • 따라서 다양한 생성자를 제공함으로써 인스턴스 생성 후에 별도로 초기화를 하지 않아도 되도록하는 것이 좋다.
class Car {
    String color;
    String gearType;
    int door;
    
    Car() {} // 생성자
    Car(String color, String gearType, Int door) {
        this.color = color;
        this.gearType = gearType;
        this.door = door;
    }
}
...
Car c = new Car("white, "auto", 4);

생성자에서 다른 생성자 호출하기 - this(), this

  • 다음 두 조건을 만족시킬 때, 생성자 간에 서로 호출이 가능하다.
    1. 생성자의 이름으로 클래스이름 대신 this를 사용한다.
    2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫줄에서만 호출이 가능하다.
Car() {
    color = "white";
    gearType = "auto";
    door = 4;
        }
        
        ↓↓
        
Car() {
    this("white", "auto", 4);
        }
  • 위 코드는 같은 일을 하지만 오른쪽 코드는 생성자 Car(String color, String gearType, Int door)을 활용하여 더 간략히 한 것이다.
  • 같은 클래스 내의 생성자들은 관계가 깊은 경우가 많으므로 서로 호출하도록하여 유기적으로 연결해주면 더 좋은 코드를 얻을 수 있다.
  • 수정이 필요한 경우에도 보다 적은 코드만을 변경하면 되므로 유지보수가 쉬워진다.
Car(String c, String g, Int d) {
        color = c;
        gearType = g;
        door = d;
        }
        
        ↓↓

Car(String color, String gearType, Int door) {
    this.color = color;
    this.gearType = gearType;
    this.door = door;
}
  • 왼쪽 코드의 ‘color = c’는 생성자의 매개변수로 선언된 지역변수 c의 값을 인스턴스변수 color에 저장한다.
  • 오른쪽 코드와 같이 생성자의 매개변수 이름과 인스턴스 변수 이름을 같게 할 경우, 인스턴스 변수 앞에 ‘this’를 붙이면 된다.
  • 생성자의 매개변수로 인스턴스 변수의 초기값을 제공받는 경우가 많으므로 이름이 일치하는 경우가 많다.
  • 이름을 다르게 하는 것보다 ‘this’로 구별하는 것이 의미가 명확하고 이해가 쉽다.

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

  • 현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있다.
Car(Car c) {
    color = c.color;
    gearType = c.gearType;
    door = c.door;
}
  • 위 코드는 Car클래스의 참조변수를 매개변수로 선언한 생성자이다.
  • 매개변수로 넘겨진 참조변수가 가리키는 Car인스턴스의 인스턴스변수인 color, gearType, door의 값을 인스턴스 자신으로 복사하는 것이다.
Car(Car c) {
    color = c.color;
    gearType = c.gearType;
    door = c.door;
}

        ↓↓

Car(Car c){
    this(c.color, c.gearType, c.door);
}
  • 생성자 ‘Car(Car c)’는 다른 생성자인 ‘Car(String color, String gearType, Int door)’를 호출하여 기존 코드를 재사용할 수 있다.

변수의 초기화

  • 변수를 선언하고 처음으로 값을 저장하는 것을 ‘변수의 초기화’라 한다.
  • 멤버변수는 자동 초기화가 이루어지나, 지역변수는 사용하기 전 반드시 초기화를 해야 한다.
int i=10, j=10; // 같은 타입의 변수는 콤마를 사용해 함께 선언하거나 초기화할 수 있다.
int i=10, long j=0; // 에러. 타입이 다른 변수는 함께 선언하거나 초기회할 수 없다.

int j=i;
int i=10;   // 에러. 변수 i가 선언되기 전에 i를 사용할 수 없다.   

멤버변수의 초기화 방법

  • 명시적 초기화, 생성자, 초기화 블럭(인스턴스 초기화 블럭, 클래스 초기화 블럭)
  • 복잡한 초기화 방법이 필요할 때 ‘초기화 블럭’ 또는 ‘생성자’를 사용한다.

초기화 블럭

  1. 클래스 초기화 블럭
    • 클래스변수의 복잡한 초기화에 사용되며, 클래스가 메모리에 처음 로딩될 때 한번만 수행된다.
  2. 인스턴스 초기화 블럭
    • 인스턴스변수의 복잡한 초기화에 사용되며, 생성자와 같이 인스턴스를 생성할 때마다 수행된다.
    • 생성자보다 인스턴스 초기화 블럭이 먼저 실행된다.
class InitBlock {
    static { /*클래스 초기화 블럭*/ }

    { /*인스턴스 초기화 블럭*/ }
}
  • 명시적 초기화를 통해 배열 arr를 생성하고, 클래스 초기화 블럭을 이용해 배열의 각 요소들을 random()을 사용하여 임의의 값으로 채우게 했다.
  • 배열이나 예외처리가 필요한 초기화에서는 추가적으로 클래스 초기화 블럭을 사용한다.
public class StaticBlockTest{

    static int[] arr = new int[10];

    static{
        for(int i=0;i<arr.length; i++){
            arr[i] = (int)(Math.random()*10) + 1;
        }
    }

    public static void main(String[] args)
    {
        for(int i=0; i<arr.length; i++)
        System.out.println("arr["+i+"] :" + arr[i]);
    }
}

멤버변수의 초기화 시기와 순서

  • 클래스 변수의 초기화 시점 : 클래스가 처음 로딩될 때 단 한번 초기화 된다.
  • 인스턴스 변수의 초기화 시점 : 인스턴스가 생성될 때마다 각 인스턴스별로 초기화가 이루어진다.
  • 클래스 변수의 초기화 순서 : 기본값 -> 명시적초기화 -> 클래스 초기화 블럭
  • 인스턴스 변수의 초기화 순서 : 기본값 -> 명시적초기화 -> 인스턴스 초기화 블럭 -> 생성자

    클래스 변수는 인스턴스 변수보다 항상 먼저 생성되고 초기화 된다.

Tags:

Categories:

Updated: