본문 바로가기
Study/JAVA

[Java] 6-5, 6. 생성자 & 변수의 초기화

by jeongwle 2022. 9. 2.
728x90
반응형

 

생성자(constructor)

1. 생성자란?

생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드이다. 인스턴스변수의 초기화 작업에 주로 사용되며 인스턴스 생성 시 실행되어야 할 작업을 위해서도 사용된다.

생성자도 메서드처럼 클래스 내에 선언되며 구조도 메서드와 유사하지만 리턴값이 없다는 점이 다르다. 하지만 일반 메서드처럼 생성자 앞에 void키워드를 사용하지 않고 아무것도 적지 않는다. 생성자의 조건은 다음과 같다.
1. 생성자의 이름은 클래스의 이름과 같아야 한다.
2. 생성자는 리턴 값이 없다.​

생성자는 다음과 같이 정의하고 오버로딩이 가능하여 하나의 클래스에 여러개의 생성자가 존재할 수 있다.
clss Card{
  Card() { // 매개변수 없는 생성자.
    ...
  }
  Card(String k, int num) { //매개변수 있는 생성자.
    ...
  }
  ...
}​

* 생성자가 인스턴스를 생성하는 것이 아니라 new 연산자가 인스턴스를 생성한다는 것에 주의하자.

Card c = new Card();

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


 

2. 기본 생성자(default constructor)

모든 클래스에는 반드시 하나 이상의 생성자가 정의되어 있어야 한다. 지금까지 클래스에 생성자를 정의하지 않고도 인스턴스를 생성할 수 있었던 이유는 컴파일러가 기본 생성자를 제공하기 때문이다. 컴파일러는 클래스에 생성자가 하나도 정의되어있지 않은 경우에 자동으로 기본 생성자를 추가하여 컴파일한다. 컴파일러가 추가한 기본 생성자는 매개변수도 없고 아무런 내용도 없다.

 

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

생성자도 매개변수를 선언하여 값을 넘겨받아 인스턴스의 초기화 작업에 사용할 수 있다.
class Car {
  String color;		// 색상
  String gearType;	// 변속기 종류
  int door;		// 문의 개수
  
  Car() {} // 생성자
  Car(String c, String g, int d) { // 생성자
    color = c;
    gearType = g;
    door = d;
  }
}​

// 매개변수 없는 생성자 사용 시
Car c = new Car();
c.color = "white";
c.gearType = "auto";
c.door = 4;

// 매개변수 있는 생성자 사용시
Car c = new Car("white", "auto", 4);

아주 편리하다!

 

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

같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 생성자 간에도 서로 호출이 가능하다. 단, 다음의 두 조건을 만족해야한다.
1. 생성자의 이름으로 클래스 이름 대신 this를 사용한다.
2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.​

this 인스턴스 자신을 가리키는 참조변수, 인스턴스의 주소가 저장되어 있다.
     모든 인스턴스메서드에 지역변수로 숨겨진 채로 존재한다.

this(), this(매개변수) 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다.​
* this를 사용할 수 있는 것은 인스턴스멤버 뿐이다. 클래스 메서드는 불가하다.

 

 

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

현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있다.
Car(Car c) {
  color = c.color;
  gearType = c.gearType;
  door = c.door;
}​

매개변수로 들어온 참조변수 c가 가리키는 인스턴스의 color, gearType, door의 값을 자기 자신으로 복사하는 것이다. 이렇게 인스턴스를 복사하더라도 서로 독립적인 메모리공간에 존재하기 때문에 복사의 대상인 인스턴스의 값이 변하더라도 복사의 결과인 인스턴스의 값에는 영향을 끼치지 않는다.

 

변수의 초기화

1. 변수의 초기화

변수의 초기화는 필수적이기도 하고 선택적이기도 하다. 하지만 가능하면 선언과 동시에 적절한 값으로 초기화 하는 것이 바람직하다. 멤버변수는 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지기 때문에 초기화하지 않고 사용해도 되지만, 지역변수는 사용하기 전에 반드시 초기화해야한다.

멤버변수의 초기화는 지역변수와 달리 여러가지 방법이 있다.
1. 명시적 초기화(explicit initialization)
2. 생성자(constructor)
3. 초기화 블럭(initialization block)
   인스턴스 초기화 블럭 : 인스턴스변수를 초기화 하는데 사용.
   클래스 초기화 블럭 : 클래스변수를 초기화 하는데 사용.​

 

2. 명시적 초기화(explicit initialization)

변수를 선언과 동시에 초기화하는 것을 명시적 초기화라고 한다. 가장 기본적이고 간단한 초기화 방법이므로 여러 초기화 방법 중에서 가장 우선적으로 고려되어야 한다. 보다 복잡한 초기화 작업이 필요할 때는 초기화 블럭 또는 생성자를 사용하자.

 

3. 초기화 블럭(initialization block)

초기화 블럭에는 클래스 초기화 블럭과 인스턴스 초기화 블럭 두 가지가 있다. 클래스 초기화 블럭은 클래스변수의 초기화에 사용되고 인스턴스 초기화 블럭은 인스턴스변수의 초기화에 사용된다. 초기화 블럭은 클래스 내에서 블럭{}을 만들고 그 안에 코드를 작성하기만 하면 된다. 클래스 초기화 블럭과 인스턴스 초기화 블럭에 차이점이라면 블럭 앞에 static의 유무이다. static이 붙으면 클래스 초기화 블럭이다.
public class InitializationBlockTest {
    static {
        System.out.println("static { }");
    }

    {
        System.out.println("{ }");
    }

    public InitializationBlockTest() {
        System.out.println("constructor");
    }

    public static void main(String[] args) {
        System.out.println("IBT bt = new IBT()");
        InitializationBlockTest bt = new InitializationBlockTest();

        System.out.println("IBT bt2 = new IBT()");
        InitializationBlockTest bt2 = new InitializationBlockTest();
    }
}​

예제를 실행해보면 클래스 초기화 블럭이 가장 먼저 실행되어 static { }이 출력된다. 그리고 인스턴스를 생성하면서 인스턴스 초기화 블럭이 실행되고 그 다음 생성자가 실행된다. 그리고 클래스 초기화 블럭은 처음 메모리에 로딩될 때 한번만 수행되지만 인스턴스 초기화 블럭은 인스턴스가 생성될 때 마다 실행되는 것을 볼 수 있다.

 

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

초기화가 수행되는 시기와 순서를 정리해보자
클래스변수의 초기화시점 : 클래스가 처음 로딩될 때 단 한번 초기화 된다.
인스턴스변수의 초기화시점: 인스턴스가 생성될 때 마다 각 인스턴스별로 초기화가 이루어진다.

클래스변수의 초기화순서 : 기본값 -> 명시적초기화 -> 클래스 초기화 블럭
인스턴스변수의 초기화순서 : 기본값 -> 명시적초기화 -> 인스턴스 초기화 블럭 -> 생성자​

 

728x90
반응형

댓글