Когда объект создается после вызова конструктора

Рассмотрим следующие классы кода.




     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!!

The first output line in the output

A Created!!
is printed because when the constructor of class A is called, it calls the super class's constructor (java.lang.Object) implicitly before calling the callCreation() method in the class A's constructor. And this will be the case for B and C classes too. In that case when the constructor of B is called the call flow should be typically : B's constructor -> A's Constructor -> java.lang.Object's Constructor -> come back to A's callCreation() method to finish calling A's constructor. If so how is the overridden value printed and not the super class's value is printed? So the question is 'when is an object of a class created exactly? to put it in other words, the object of a class should be created only after the constructor finishes calling/initializing all the elements within itself. If so how can a method be called from a child class and not from the parent class?


person user1223879    schedule 21.02.2012    source источник


Ответы (2)


Методы callCreation в B и C переопределяют метод из A. Таким образом, когда метод вызывается в конструкторе A, будут запущены реализации в B и C, даже если конструкторы B и C не казнен еще. Это возможно, потому что конструкторы на самом деле не создают объект, а вызываются для инициализации через некоторое время после его создания JVM.

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

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

    protected void callCreation()
    {
        System.out.println("B Created!! "+msg);
    }
}
person Joni    schedule 21.02.2012
comment
+1 Точно - он всегда вызывается из одного и того же конструктора. Разница только в том, куда идет вызов. - person Paul Bellora; 21.02.2012
comment
Разве jvm не нужен объект для вызова метода на нем? Пожалуйста, найдите мой комментарий в ответе ниже. - person user1223879; 21.02.2012
comment
Да; на самом деле ему также нужен объект для запуска конструктора. Объект существует задолго до выполнения конструктора. - person Joni; 21.02.2012
comment
Я немного смущен здесь. Как объект может существовать до того, как он будет создан? - person user1223879; 21.02.2012
comment
Термин конструктор вводит в заблуждение. На самом деле это просто специальные методы, которые вызываются вскоре после того, как JVM создала объект. - person Joni; 21.02.2012
comment
@ user1223879 - Джони права. Хорошим примером является использование this в конструкторах; к моменту вызова конструктора у вас уже есть объект в памяти, на который можно ссылаться. Вот почему утечка ссылок на this до завершения конструктора может быть проблематичной. - person Paul Bellora; 21.02.2012
comment
Спасибо за ваши комментарии и идеи Джони и Пол. Теперь я получил общее представление о том, что происходит при вызове конструктора. Хотя я знал, как это работает, я хотел знать, почему это работает именно так, и понял :) Спасибо за ваш вклад... - person user1223879; 22.02.2012

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

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

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

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

}

класс B расширяет A {

public B() {
    super();
}

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

}

класс C расширяет 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();

}

}

person Sina Barghidarian    schedule 17.03.2013