인스턴스 이니셜 라이저는 생성자와 어떻게 다릅니 까?


82

즉, 인스턴스 이니셜 라이저가 필요한 이유는 무엇입니까? 생성자보다 인스턴스 이니셜 라이저를 작성할 때 어떤 차이점이나 이점이 있습니까?


2
인스턴스 이니셜 라이저는 매우 드뭅니다 (이중 중괄호 관용구를 좋아하는 사람의 코드에 부딪히지 않는 한).
Tom Hawtin-tackline

답변:


109

이것은 잘 설명하는 것 같습니다.

인스턴스 이니셜 라이저는 다음과 같은 경우 인스턴스 변수 이니셜 라이저의 유용한 대안입니다.

  • 이니셜 라이저 코드는 예외를 포착해야합니다.

  • 인스턴스 변수 이니셜 라이저로 표현할 수없는 멋진 계산을 수행합니다. 물론 생성자에서 이러한 코드를 항상 작성할 수 있습니다.

그러나 여러 생성자가있는 클래스에서는 각 생성자에서 코드를 반복해야합니다. 인스턴스 이니셜 라이저를 사용하면 코드를 한 번만 작성할 수 있으며 객체를 생성하는 데 사용되는 생성자가 무엇이든 상관없이 실행됩니다. 인스턴스 이니셜 라이저는 생성자를 전혀 선언 할 수없는 익명의 내부 클래스에서도 유용합니다.

From : Java에서 JavaWorld 객체 초기화 .


17
반면에 하나의 생성자에서 코드를 한 번 작성하고 다른 모든 생성자에서 호출 할 수 있습니다. 그러나 익명의 내부 클래스는 좋은 지적을합니다.
Tadeusz Kopec

11
다른 생성자에서 호출 할 수 있지만 다시 호출을 반복합니다. 새 생성자를 추가하는 경우 호출을 추가해야합니다. 인스턴스 이니셜 라이저에서는 그렇지 않습니다.
talonx

5
@talonx, 망각에 대한 귀하의 주장에 동의하지만 기본 동작을 사용하는 것은 똑같이 위험합니다. 지원자가 레거시 코드의 생성자를 통해 읽을 때 가능한 인스턴스 이니셜 라이저를 항상 확인하는 것을 기억하지 못할 것입니다. 명시 적으로 사용되는 init ()가 눈에.니다.
Assambar

1
@ javamonkey79 : 내 클래스의 인스턴스 이니셜 라이저 보다 생성자 를 선택하면 인스턴스 이니셜 라이저가 유용한 유일한 곳은 익명 클래스로 작업 할 때라는 말입니까?
realPK

4
@Assambar init () 메서드에서 최종 필드를 할당 할 수 없지만 초기화 블록에서는 할 수 있습니다.
Timmos

22

개체 수명주기 측면에서 차이가 없습니다. 둘 다 생성시에 호출되며 논리적으로 초기화 블록은 생성의 일부로 간주 될 수 있습니다.

의미 상 이니셜 라이저는 여러 가지 이유로 좋은 도구입니다.

이니셜 라이저는 초기화되는 변수 옆에 초기화 로직을 유지하여 코드 가독성을 향상시킬 수 있습니다.

   public class Universe {
       public int theAnswer;
       {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;
       }

       // a bunch of other vars
   }

vs

   public class Universe {
       public int theAnswer;

       // a bunch of other vars

       public Universe() {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;

         // other constructor logic
       }
   }

이니셜 라이저는 사용되는 생성자에 관계없이 호출됩니다.

이니셜 라이저는 생성자가 할 수없는 익명의 내부 클래스에서 사용할 수 있습니다.


3
당신이 가지고있는 것은 기술적으로 "인스턴스 이니셜 라이저"(클래스 내에 직접 중첩 된 블록)가 아니라 "인스턴스 변수 이니셜 라이저"입니다. JLS 3rd 섹션 8.6을 참조하십시오.
Tom Hawtin-tackline

인스턴스 이니셜 라이저 블록에는 여기에 표시된 이름이 없습니다 . 그렇지 않나요? 인스턴스 이니셜 라이저 코드를 name으로 표시했습니다 theAnswer. 그 맞습니까? 아니면 뭔가 빠졌어요.
RBT

1
@RBT theAnswer는 선언 된 인스턴스 변수입니다. 익명 이니셜 라이저 블록에서 초기화됩니다. 변수 선언 뒤의 세미콜론에 유의하십시오.
ykaganovich

10

생성자가 많고 각 생성자에 대해 공통 코드를 실행하려면 인스턴스 이니셜 라이저를 사용할 수 있습니다. 모든 생성자에 대해 호출되므로


4

일반적으로 인스턴스 이니셜 라이저 관용구를 피할 것입니다. 변수 이니셜 라이저에 비해 유일한 실제 이점은 예외 처리입니다.

그리고 init 메서드 (생성자에서 호출 가능)도 예외 처리를 수행하고 생성자 설정 코드를 중앙 집중화 할 수 있지만 생성자 매개 변수 값에 대해 작동 할 수 있다는 이점이 있기 때문에 인스턴스 이니셜 라이저가 중복되므로 피했다.


1
모든 생성자에서 init 메서드를 수동으로 호출해야합니다.
Stephan

2
@Alex 좋은 지적이지만 여러 생성자를 가진 대부분의 클래스는 공통 논리를 가지고 있기 때문에 어쨌든 서로를 호출하는 경향이 있습니다. 적어도 대부분의 수업에서.
CPerkins 2013-10-29

3

생성자에 비해 인스턴스 이니셜 라이저진정한 이점은 익명의 내부 클래스를 사용할 때 볼 수 있습니다 .

익명 내부 클래스는 생성자를 가질 수 없습니다 (그들이있는 거 익명으로) , 그래서 그들이 꽤 잘 맞는다있어 인스턴스 초기화 .


1

객체 생성시 인스턴스 변수의 초기화를 수행하려면 생성자에 가야합니다. 객체 생성시 어떤 활동을 수행하려면 초기화 활동이 아닌 생성자로 가야하며 인스턴스 블록으로 가야합니다.

생성자는 인수를받을 수 있지만 인스턴스 블록은 인수를받을 수 없기 때문에 생성자를 인스턴스 블록으로 바꿀 수 없습니다.

클래스가 하나 이상의 생성자를 포함 할 수 있기 때문에 생성자 인스턴스 블록을 대체 할 수 없습니다. 인스턴스 블록을 생성자로 대체하려면 모든 생성자에서 인스턴스 블록 코드를 작성해야합니다. 런타임시 어떤 생성자가 호출 될지 예상 할 수 없기 때문에 중복 코드가 불필요하게 증가합니다.

예 :

class MyClass{

    static int object_count = 0;

    MyClass(){
        object_count++;
    }

    MyClass(int i){

        object_count++;
    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

출력 : 2

class MyClass{

    static int object_count = 0;

    {
        object_count++;
    }

    MyClass(){

    }

    MyClass(int i){     

    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

출력 : 2


0

이니셜 라이저는 생성자간에 코드를 공유하는 방법이며 변수 선언과 함께 이니셜 라이저를 사용하면 코드를 더 읽기 쉽게 만듭니다.

Java 컴파일러는 이니셜 라이저 블록을 모든 생성자로 복사합니다. 따라서이 방법을 사용하여 여러 생성자간에 코드 블록을 공유 할 수 있습니다. Oracle 문서

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.