2012-02-21 3 views
0

Рассмотрим следующие классы кода.Когда объект создается после того, как конструктор называется




    public class A 
    { 
     public A() 
     { 
      callCreation(); 
     } 

     protected void callCreation() 
     { 
      System.out.println("A Created!!"); 
     } 
    } 




    public class B extends A 
    { 
     protected void callCreation() 
     { 
      System.out.println("B Created!!"); 
     } 
    } 


    public class C extends B 
    { 
     protected void callCreation() 
     { 
      System.out.println("C Created!!"); 
     } 

     public static void main(String[] args) 
     { 
      A a = new A(); 
      A b = new B(); 
      A c = new C(); 
     } 
    } 

Результат работы класса C приведен ниже.

 
A Created!! 
B Created!! 
C Created!! 

Первый линейный выход на выходе

A Created!!
печатается, потому что, когда конструктор класса А называется, он вызывает конструктор суперкласса (в java.lang.Object) неявно перед вызовом метода callCreation() в класс А. И это будет иметь место и для классов B и C. В этом случае, когда конструктор B называется потоком вызова, должен быть типичным: конструктор B -> A Constructor -> java.lang.Object's Constructor -> возвращается к методу callCreation() для завершения вызова конструктора A. Если да, то как печатается переопределенное значение, а не значение суперкласса? Таким образом, возникает вопрос: «Когда объект точно создан? иначе говоря, объект класса должен быть создан только после того, как конструктор завершит вызов/инициализацию всех элементов внутри себя. Если да, как можно вызывать метод из дочернего класса, а не из родительского класса?

ответ

4

В callCreation метод в В и С переопределением метода от А. Таким образом, когда метод вызывается в конструкторе реализации в В и С будут запускаться, даже при том, что конструкторы В и С не были выполнено еще. Это возможно, потому что конструкторы фактически не создают объект, а они вызываются в , инициализируя через несколько мгновений после создания JVM.

В целом, это очень плохая идея вызывать методы, которые могут быть переопределены конструктором именно по этой причине. Метод в B или C может предполагать, что инициализаторы конструктора и объекта уже запущены и считывают неожиданное значение из поля. Например, следующее завершается печатью "B Created!! null", потому что этому полю еще не присвоено его значение.

public class B extends A 
{ 
    final String msg = "Yes!"; 

    protected void callCreation() 
    { 
     System.out.println("B Created!! "+msg); 
    } 
} 
+0

+1 Точно - он всегда вызывается из одного и того же конструктора. Единственное различие заключается в том, где идет звонок. –

+0

Неужели jvm нужен объект для вызова метода на нем? Пожалуйста, найдите мой комментарий в ответе ниже. – user1223879

+0

Да; на самом деле ему также нужен объект, для которого нужно * запустить конструктор *. Объект существует задолго до того, как конструктор будет выполнен. – Joni

0

мышление таким образом делает его более очевидным: , когда объект типа B создается супер() ключевое слово вызывает конструктор, затем в конструктор «this.callCreation()» выполняется, который относится к текущему объекту , который является B, поэтому вызывается callCreation, соответствующая текущему объекту (B). тот же самый процесс делается для C.

общественного класса А {

public A() { 
    this.callCreation(); 
} 

protected void callCreation() { 
    System.out.println("A Created!!"); 
} 

}

класс В Расширяет {

public B() { 
    super(); 
} 

protected void callCreation() { 
    System.out.println("B Created!!"); 
} 

}

класс С простирается B {

public C() { 
    super(); 
} 

protected void callCreation() { 
    System.out.println("C Created!!"); 
} 

public static void main(String[] args) { 

     A a = new A(); 
     A b = new B(); 
     A c = new C(); 

} 

Смежные вопросы