Методы вызова внутри Constructor
Ниже я имею два класса. Парент и ребенок. Класс Child наследуется от класса Parent. В конструкторе класса родителя я вызываю метод print() родительского класса.
Когда я создаю объект Object для класса Child в методе main(), запускается конструктор класса Parent, и вместо метода родительского класса print() вызывается метод print() класса Child.
Q1. Почему это происходит.
Q2. Почему значение я равно 0
public class Sample
{
public static void main(String[] args)
{
Child objChild = new Child();
objChild.print();
}
}
class Parent
{
void print()
{
System.out.println("i Value");
}
Parent()
{
print();
}
}
class Child extends Parent
{
int i = 45;
void print()
{
System.out.println("i Value = "+i);
}
}
ОП
i Value = 0
i Value = 45
Ответы
Ответ 1
Причина, по которой вызван дочерний метод, заключается в том, что отправка виртуального метода является нормой в Java. Когда вы вызываете метод, он решает, какой метод фактически вызывается во время выполнения на основе фактического типа объекта.
Что касается того, почему он печатает 0, это потому, что i
еще не установлено на 45. Каждое поле инициализируется значением по умолчанию для этого типа, 0
в случае целых чисел. Когда вы пишете int i = 45
, компилятор будет генерировать код в конструкторе для установки i = 45
. Но он помещает этот код после вызова родительского конструктора. Поэтому вы печатаете переменную до ее инициализации с ее предполагаемым значением.
Ответ 2
На самом деле у Java есть довольно четкие правила. По сути, код "int я = 45" в подклассе является неявной частью конструктора подкласса, и сначала выполняется суперкласс всегда.
Порядок событий:
- Создайте объект и обнулите все переменные экземпляра.
- Вызывать инициализаторы суперкласса.
- Вызывать конструктор суперклассов.
- Вызывать инициализаторы подкласса (int я = 45, в этом примере)
- Вызывать конструктор подкласса.
Это становится очень неприятным, когда у вас есть последнее поле. Вы можете объявить окончательный "i" в своем примере и получить тот же результат!
В общем, вызов не-частных (или, по крайней мере, не конечных) методов в конструкторе требует неприятностей и часто является источником неприятных ошибок. Вызов абстрактного метода - это плохая идея действительно (большую часть времени).
Ответ 3
Java Beginner. У меня возникла ваша проблема.
1.Когда вы создаете объект дочернего класса в то время print(), вызванный только в дочернем классе, не в родительском классе, даже если конструктор родительского класса, называемый первым bcoz, объект имеет дочерний класс
Пожалуйста, обратитесь к следующему примеру.
public class Test
{
public static void main(String[] args)
{
//create the object of child class
Child child = new Child();
}
}
class Parent
{
void print()
{
System.out.println("parent>> i ValueOne=");
}
Parent()
{
System.out.println("parent>> i ValueTwo=");
print();
}
}
class Child extends Parent
{
int i = 45;
void print()
{
System.out.println("Child>>i Value = "+i);
}
}
Выход:
parent>> i ValueTwo=
Child>>i Value = 0
2.Если вы создаете объект родительского класса, в это время вызывается метод print() в родительском классе.
Пожалуйста, обратитесь к следующему примеру.
public class Test
{
public static void main(String[] args)
{
//create the object of Parent class
Parent parent = new Parent();
}
}
class Parent
{
void print()
{
System.out.println("parent>> i ValueOne=");
}
Parent()
{
System.out.println("parent>> i ValueTwo=");
print();
}
}
class Child extends Parent
{
int i = 45;
void print()
{
System.out.println("Child>>i Value = "+i);
}
}
Выход:
parent>> i ValueTwo=
parent>> i ValueOne=
3. И я думаю, вы уже поняли, почему это значение я равно 0 или 45.
Ответ 4
Потому что в это время первого вызова метода печати i
не инициализируется до 45, поэтому его печать 0.
вызов выглядит следующим образом
- дочерний конструктор (как из-за цепочки конструктора от дочернего к родительскому)
- родительский конструктор
- метод печати (теперь здесь
i
не инициализирован дочерний конструктор coz еще не завершен, поэтому он печатает значение по умолчанию i
, которое равно 0)
- теперь после завершения родительского конструктора, а затем дочерний конструктор
i
получает значение, равное 45 -
- поэтому теперь он печатает 45 при следующем вызове метода печати
Ответ 5
Во-первых, я не вижу определения конструктора в вашем классе Child
.
Если вы не определяете конструктор для класса Child
, его конструктор по умолчанию:
public Child() {
super();
}
Где super();
вызывает конструктор класса Parent
(суперкласс).
Однако вы определили свой метод print()
в классе Child
, и поскольку он имеет такую же подпись (параметр name +), что и метод в классе Parent
, он переопределяет метод суперкласса с той же сигнатурой.
Вот почему ваш класс Child
вызывает конструктор класса Parent
, тогда как он вызывает свой собственный метод print()
.
Добавленный:
Первое значение я равно 0, потому что вы не инициализировали int-переменную i
в классе Parent
, а значение неинициализированной переменной int равно 0 по умолчанию. После вызова Parent
он вызывает теперь метод Child
print()
, а i
инициализируется в классе Child
, поэтому теперь i
- это значение, которое вы инициализировали
Ответ 6
Ваш ребенок сначала вызывает ваш родительский конструктор. На этом этапе я не инициализируется значением 45. Поэтому он печатает 0 (значение по умолчанию int).