반응형

빈도가 되게 높다고는 할 수 없는 부분이지만, 

빼놓을 수도 없는 부분인 인스턴스 초기화 블럭 파트입니다.!

일단 , 쓰임새에 대해서 알아볼까요?


1)     인스턴스 데이터 멤버를 초기화 인스턴스 초기화 블록을 사용합니다.

2)    클래스의 객체가 생성될 마다 인스턴스 초기화 블록이 실행됩니다.


초기화 블럭의 정의 아래와 같습니다.

 

초기화 블럭(initialization block)

클래스 초기화 블럭 : 클래스 변수의 복잡한 초기화에 사용된다. 클래스가 처음 로딩될 한번만 수행된다.

인스턴스 초기화 블럭 : 인스턴스 변수의 복잡한 초기화에 사용된다. 인스턴스가 생성될때 마다 수행된다. (생성자보다 먼저 수행된다.)


Q)아래 코드처럼 개발자 직접 인스턴스 데이터 멤버에 값을 있는데,

굳이 인스턴스 초기화 블럭을 사용하나요?


class bike {

int speed = 100;

}



A) 인스턴스 초기화 블럭을 사용하는가?


인스터스 데이터 멤버에 값을 할당하면서 for 반복문으로 복잡한 배열이나 에러 처리 같은 어떤

작을 수행해야한다고 가정해봅시다.


package instance_initialize_block;


public class InstanceTest01 {

public static void main(String[] args) {

bike7 b1 = new bike7();

bike7 b2 = new bike7();

}


}


class bike7{

int speed;

public bike7() {

System.out.println("speed = " + speed);

// TODO Auto-generated constructor stub

}

{speed = 100;}

}

output=

speed = 100

speed = 100


여기서보면, 

bike7 클래스안에 별도의 {}블럭이 생성되어있고 

 speed = 100;으로 초기화시켜주고있네요.

일단 인스턴스 초기화 블럭의 모양이 저런 모양이구나 하고 넘어가봅시다.

자바에서 동작을 수행할 있는 곳은 세 곳이 있습니다.

  1. 메소드
  2. 생성자
  3. 블럭<<<<

그렇다면, 블럭이 위치한 로컬에 있는 변수의 초기값을 블럭의 내용대로 적용이 된것을 알 수가 있겠죠?

———————

 그렇다면, 인스턴스 블럭과 생성자 중에 무엇이 먼저 실행 될까요?


예제를 살펴보죠,

package instance_initialize_block;


public class InstanceTest02 {

public static void main(String[] args) {

bike8 b1 = new bike8();

bike8 b2 = new bike8();

}

}


class bike8{

int speed;

public bike8() {

System.out.println("생성자가 호출되었습니다.");

//생성자 

}

{System.out.println("인스턴스 초기 블럭이 호출되었습니다.");}

// 인스턴스블럭 

}




bike8이라는 테스트용 클래스를 만든 후 

생성자에 프린트를 찍어줍니다.

그리고 블럭을 삽입해 둘 중 누가 먼저 실행될지에 대해서 테스트해보도록하죠.


메인 메소드를 가지고있는 InstanceTest02 클래스에

bike8클래스 객체를 만들어서 테스트해보도록하겠습니다.

위 상태로 실행시키면, b1이 실행되고 b2가 실행되겠죠.

이때 생성자가 먼저 호출이 될건지, 블럭이 먼저 호출이 될건지 봅시다.



의외로 생성자가 먼저 호출이 된 결과값이네요.

왜그런지 알아볼까요?


실은, 인스턴스 초기화 블럭이 먼저 호출이 되는 것처럼보이지만은,

객체가 생성될때 인스턴스 초기화 블럭이 호출됩니다. ( 거의 동시에)

자바 컴파일러는 첫 문장 super() 키워드 이후에 생성자 안에 있는 인스터스 초기화 블럭을 카피합니다.

그래서 결과값과는 살짝 다르게 생성자를 먼저 호출하는 셈이죠.

아래에 이해를 돕는 예제와 표를 첨부했습니다.

위에 표에서는 숨어있던 super()가 나오네요 !

실행 순서는

super() > instance initialize block > constructor of local 순서가 되겠네요.

bike클래스가 상속받을 parentOfBike클래스를 만들어주고

생성자에 프린트문으로 찍어줍니다.(누가 먼저 호출되는지 구분하기위해서)

별 다른 설명이 없습니다.

실행하였을때 

super()로 부모클래스의 생성자가 호출되고

인스턴스 초기화 블럭에 있던 구문이 실행되고

로컬 클래스에 생성자가 호출되었네요.

이제 이해가 가시나요?

안가신다면 잠시 여유를 가져보는 건 어떨까요?

인스턴스 초기화 블럭은 주된 3가지 규칙에 의해 사용되는데 

아래와 같습니다.

1) 인스턴스 초기화 블럭은 클래스의 인스턴스가 생성될 때 생성됩니다.

2)부모 클래스 생성자를 호출한 후 인스턴스 초기화 블럭이 호출됩니다.

3) 인스턴스 초기화 블럭은 기술된 순서대로 나타납니다.

마지막 예제를 보시죠!

부모 클래스를 만들고~

A를 상속할 B3클래스를 만들어주고~

생성자에 super()키워드를 넣어줍니다.

오버로드한 생성자에 int a라는 매개 변수를 삽입하고

B3클래스 최하단에 인스턴스 초기화 블럭을 선언해줍니다.

그리고는 객체를 만들 때 매개변수를 준 객체와 안준 객체를 

생성하면 어떻게 될까요?

결과값을 보면 이해가 잘 되시나요?

다시한번 되짚어보자면

super() > instance initializer block > constructor of local class.

꼭 기억하시고 열공하시길 바랍니다 :)


반응형
by 발전소장 에르 :) 2017. 8. 6. 18:35