2017-01-28 2 views
0

Java의 필드 초기화에 이상한 순서가 있다는 것을 발견했을 때 나는 혼란 스러웠습니다. 초기화() 결과가 필드 초기화를 덮어 씁니다 예제 코드 :처음 사용하기 전에 필드가 초기화되지 않은 이유는 무엇입니까?

public abstract class Parent { 

    public String parentField = "dupa"; 

    public Parent(){ 
     init(); // uhh, bad practice to call abstract method in a super constructor 
    } 

    protected abstract void init(); 
} 

public class Child extends Parent { 

    public String childField = null; // assigning null is unnecessary, another bad practice 

    @Override 
    protected void init(){ 
     childField = "initialized"; 
     System.out.println("After init(): " + childField); 
    } 
} 

... 

Child child = new Child(); // OUTPUT: After init(): initialized 
System.out.println("After all: " + child.childField); // OUTPUT: After all: null 

내가 new Child();를 호출 할 때 실행 순서가 무엇인지 발견

  1. 부모 필드 초기화하지만 childField이 이미 존재하고 기본 설정되어 있습니다 값 (childField = NULL)
  2. 상위 생성자 부모 생성자 호출
    • 오버라이드 초기화() (CH2 내가이 예 나쁜 관행이 가득 알고 childField = null이 (다시)
    • 아이 생성자

: ildField =

  • 아이 초기화 필드) "초기화". 그러나 나를위한 직관적 인 순서는 필드 초기화 (부모에서 자식으로), 생성자 (부모에서 자식으로)입니다.

    이러한 초기화 순서의 목적은 무엇입니까? 필드 이니셜 라이저가 잠재적으로 처음 사용되기 전에 실행되지 않는 이유는 무엇입니까? 필드가 아직 초기화되지 않았 으면 필드를 사용할 수없는 이유는 무엇입니까?

  • +0

    ''부모 '에 대한 ctor가 끝나기 전에'childField'가'Child'에서 어떻게 초기화 될까요? –

    +0

    생성자에서 재정의 할 수있는 메서드를 호출하는 이유는 불완전한 개체가 다른 코드로 누설된다는 점입니다. 마찬가지로, 자식 필드 이니셜 라이저는'super'가 완전히 생성 될 것으로 기대합니다. – 4castle

    +0

    자식 및 부모 모두에서 params와 함께 생성자를 사용하는 경우 자식 생성자가 자체 생성자 코드보다 먼저 부모를 호출해야합니다. 이런 종류의 질문을 내게 보입니다. – efekctive

    답변

    2

    나 새로운 객체 건설의 당신의 "직관적 인"위해 의역하자

    1. 부모의 필드를 초기화를
    2. 자녀의 필드가 부모의 생성자를 호출
    3. 초기화
    4. 가 자녀의 생성자가 호출

    글쎄, 아이의 f ields는 부모에 종속적 일 수 있습니다.

    개체는 생성자가 반환 될 때 "적절히 초기화 된"것으로 간주 할 수 있습니다. 동의하다?

    ParentChild 대신에 BoxTreasureBox을 사용합니다. TreasureBox을 구성하려면 Box으로 시작하십시오. 상자를 만든 후에는 멋진 데코레이션을 추가하여 멋지고 시원하게 보이게하고 자물쇠 또는 기타 등을 추가 할 수도 있습니다.

    참조? 여기 명령? 자식을 초기화하기 전에 먼저 부모를 올바르게 초기화하는 것이 가장 좋습니다. 즉, 부모 클래스의 생성자가 반환 된 후에 자식 클래스의 초기화가 발생해야합니다. 이것이 바로 Java가하는 일입니다.

    하위 필드는 상위 필드에 종속 될 수 있습니다. TreasureBox에 자물쇠를 넣으려면 상자의 앞면을 찾아서 그 위에 놓아야합니다. 상자의 앞면이 아직 만들어지지 않았다면 어떻게 자물쇠를 끼울 수 있습니까?

    class Parent { 
    
        public String parentField; 
    
        public Parent(){ 
         parentField = "Hello"; 
        } 
    } 
    
    class Child extends Parent { 
    
        public int childField = parentField.length(); 
    } 
    

    자바가 "직관적"순서를 사용하는 경우

    이하는 NPE가 발생합니다 :

    는 여기에 내가 무엇을 의미하는지 명확하게 몇 가지 코드입니다.

    +0

    하나의 체계가 생성자의 필드 초기화 프로그램과 종속 값에 상수 값만 할당하는 경우 두 명령간에 차이가 없습니다. 귀하의 예제 코드는 반대 스키마를 사용합니다. – igrek51