생성자와 변수의 초기화

jungnoeun·2022년 5월 9일

java

목록 보기
7/22

생성자란?

  • 생성자는 인스턴스가 생성될때 호출되는 "인스턴스 초기화 메서드" 이다.
  • 변수의 초기화 작업에 주로 사용된다.
  • 인스턴스 생성시에 실행되어야 할 작업을 위해서도 사용된다.
  • 메서드처럼 클래스내에 선언된다.
  • 생성자는 오버로딩이 가능하여, 하나의 클래스에 여러개의 생성자가 존재할 수 있다.



생성자의 조건
1. 생성자의 이름은 클래스의 이름과 같아야 한다.
2. 생성자는 리턴값이 없다.

연산자 new가 인스턴스를 생성하는 것이지 생성자가 인스턴스를 생성하는 것이 아니다.



Card클래스의 인스턴스를 생성하는 과정
Card c = new Card();

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





기본 생성자

  • 컴파일할 때, 소스파일(.java)의 클래스에 생성자가 하나도 정의되지 않은경우 컴파일러는 자동적으로 매개변수도 없고, 아무 내용도 없는 "기본 생성자"를 자동으로 추가해준다.

단, 기본 생성자가 컴파일러에 의해 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을때 뿐이다.






매개변수가 있는 생성자

  • 생성자도 메서드처럼 매개변수를 선언하여 호출 시 값을 넘겨받아서 인스턴스의 초기화 작업에 사용할 수 있다.
//예제
class Car {
	String color;
    String gearType;
    int door;
    
    //매개변수가 없는 생성자
    Car() {}
    
    //매개변수가 있는 생성자
    Car(String c, String g, int d) {
    	color = c;
        gearType = g;
        door = d;
    }
}






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

  • 같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 생성자간에도 서로 호출이 가능하다.

    단, 생성자간 호출에는 두가지 조건을 만족시켜야 한다.

    1. 생성자의 이름으로 클래스이름 대신 this를 사용한다.
    2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.

아래는 위의 두가지 조건을 충족시키지 못한 오류코드의 예이다.

Car(String color) {
	door = 5;
    Car(color, "auto", 4); //에러1. 생성자의 두번째줄에서 다른 생성자를 호출
    //에러2. this(color, "auto", 4);로 해야 한다.

}



  • 생성자의 매개변수로 선언된 변수의 이름이 color로 인스턴스 변수의 이름과 같은 경우, 이름만으로는 두 변수가 서로 구별이 안된다.
  • 이런 경우에는 인스턴스변수 앞에 'this'를 사용해준다.

아래와 같이 this.color는 인스턴스 변수이고, color는 생성자의 매개변수로 정의된 지역변수로 서로 구별이 가능하다.

Car(String color, String gearType, int door) {
	this.color = color;
    this.gearType = gearType;
    this.door = door;
}

this

  • this는 참조변수로 인스턴스 자신을 가리킨다. 참조변수를 통해 인스턴스의 멤버에 접근할 수 있는 것처럼 this로 인스턴스 변수에 접근할 수 있는 것이다.
  • this를 사용할 수 있는 것은 인스턴스멤버뿐으로 static메서드(클래스 메서드)에서는 인스턴스 멤버들을 사용할 수 없는 것처럼 'this'역시 사용불가하다.
    - 왜냐하면 static메서드는 인스턴스를 생성하지 않고도 호출될 수 있어서 static메서드가 호출된 시점에 인스턴스가 존재하지 않을 수 있기 때문이다.
  • 생성자를 포함한 모든 인스턴스메서드에는 자신과 관련된 인스턴스를 가리키는 참조변수 'this'가 지역변수로 숨겨진채로 존재한다.

this

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


    this(), this(매개변수)
  • 생성자, 같은 클래스의 다른 생성자를 호출할때 사용한다.


    참고
  • thisthis()는 비슷하게 생겼을뿐 완전히 다른 것이다. this는 '참조변수'이고, this()는 '생성자'이다.






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

  • 아래의 코드와 같이 Car클래스의 참조변수를 매개변수로 선언한 생성자를 이용해 같은 상태를 같은 두개의 인스턴스를 만들 수 있다.
Car(Car c) {
	color = c.color;
    gearType = c.gearType;
    door = c.door;
}

인스턴스를 생성할때 결정해야 할 2가지 사항
1. 클래스 - 어떤 클래스의 인스턴스를 생성할 것인가?
2. 생성자 - 선택한 클래스의 어떤 생성자로 인스턴스를 생성할 것인가?








변수의 초기화

  • 변수를 선언하고 처음으로 값을 저장하는 것을 '변수의 초기화'라고 한다.
  • 멤버변수는 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지지만 지역변수는 사용하기 전에 반드시 초기화해야 한다.
class InitTest {
	int x; 		//인스턴스 변수
    int y = x;	//인스턴스 변수
    
    void method1() {
    	int i;		//지역변수
        int j = i;  // 에러. 지역변수를 초기화하지 않고 사용
    }
}

멤버변수(클래스변수와 인스턴스변수)와 배열의 초기화는 선택적이지만 지역변수의 초기화는 필수적이다.

각 타입의 기본값(default value)은 아래와 같다.


멤버변수의 초기화 방법
1. 명시적 초기화 (explicit initialization)
2. 생성자 (constructor)
3. 초기화 블럭 (initialization block)
- 인스턴스 초기화 블럭 : 인스턴스 변수를 초기화하는데 사용.
- 클래스 초기화 블럭 : 클래스 변수를 초기화하는데 사용.





명시적 초기화 (explicit initialization)

  • 변수를 선언과 동시에 초기화하는 것을 '명시적 초기화'라고 한다.
class Car {
	int door = 4; 			 // 기본형(primitive type) 변수의 초기화
    Engine e = new Engine(); // 참조형(reference type) 변수의 초기화
}
  • 명시적 초기화가 간단하고 명료하지만, 보다 복잡한 초기화 작업이 필요할 때는'초기화 블럭(initialization block)'또는 생성자를 사용해야 한다.






초기화 블럭(initialization block)

  • 초기화 작업이 복잡하여 명시적 초기화만으로는 부족한 경우 초기화 블럭을 사용한다.

    초기화 블럭의 두가지 종류

    • 클래스 초기화 블럭
      클래스 변수의 복잡한 초기화에 사용된다.
    • 인스턴스 초기화 블럭
      인스턴스변수의 복잡한 초기화에 사용된다.
class InitBlock {
	static { /* 클래스 초기화 블럭입니다.
    인스턴스 초기화 블럭앞에 단순히 static을 붙이면 된다.*/}
    
    {/*인스턴스 초기화 블럭입니다.*/}
}
  • 클래스 초기화 블럭은 클래스가 메모리에 처음 로딩될 때 한번만 수행되고, 인스턴스 초기화 블럭은 생성자와 같이 인스턴스를 생성할때마다 수행된다.
  • 클래스의 모든 생성자에 공통으로 수행되어야 하는 문장들이 있을 때, 이 문장들을 각 생성자마다 써주기 보다는 인스턴스 블럭에 넣어주면 코드가 보다 간결해진다.
  • 코드의 중복을 제거하는 것은 코드의 신뢰성을 높이고, 오류의 발생가능성을 줄여준다.






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

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




//예시
class InitTest {
	static init cv = 1;	// 명시적 초기화
    int iv = 1;			// 명시적 초기화
    
    static { cv = 2; }	// 클래스 초기화 블럭
    { iv = 2; }			// 인스턴스 초기화 블럭
    
    InitTest () {		// 생성자
    	iv = 3;
    }
}

클래스 변수는 인스턴스 블럭이 몇번 수행되는지와 관계없이 모든 인스턴스 블럭에 대해 같은 값을 갖는다.

profile
개발자

0개의 댓글