Не понятно почему по окончании работы конструктора не происходит возвращение в main(), а выполняется код далее в классе

Рейтинг: 2Ответов: 1Опубликовано: 19.02.2023

Почему после завершения работы конструктора NormalMember() на строке 27 не происходит возвращение в main() на сторку 8, а происходит попытка создания NormalMember myChildMember = new NormalMember("James", 1, 2010); - следующая строка кода - 42

 1 import static java.lang.System.out;
 2
 3 public class InheritanceDemo
 4 {
 5    public static void main(String[] args)
 6    {
 7         NormalMember mem1 = new NormalMember("James", 1, 2010);
 8         VIPMember mem2 = new VIPMember("Andy", 2, 2011);
 9
10         mem1.displayMemInfo();
11         mem2.displayMemInfo();
12     }
13 }
14 class Member
15 {
16     private String name;
17     private int memberID;
18     private int memberSince;
19
20     public Member(String pName, int pMemberID, int pMemberSince)
21     {
22         out.println("Parent Constructor with 3 parameters");
23
24         name = pName;
25         memberID = pMemberID;
26         memberSince = pMemberSince;
27     }
28     public void displayMemInfo()
29     {
30         out.println("Member Name is " + name);
31         out.println("Member ID is " + memberID);
32         out.println("Member Since " + memberSince);
33     }
34 }
35 class NormalMember extends Member
36 {
37     public NormalMember(String pName, int pMemberID, int pMemberSince)
38     {
39         super (pName, pMemberID, pMemberSince);
40         out.println("Child Constructor with 3 parameters");
41     }
42     NormalMember myChildMember = new NormalMember("James", 1, 2010);
43 }
44 class VIPMember extends Member
45 {
46     public VIPMember(String pName, int pMemberID, int pMemberSince)
47     {
48         super(pName, pMemberID, pMemberSince);
49         out.println("Child Constructor with 3 parameters");
50     }
51 }

Ответы

▲ 2Принят

После обработки конструктора базового класса сначала будут проинициализированы поля класса-потомка, и к несчастью класс NormalMember содержит не нулевое поле, которое начинает инициализироваться до вызова конструктора NormalMember, соответственно, снова запускается вся цепочка: поля базового класса, конструктор базового класса, и снова запускается инициализация нового экземпляра NormalMember и так до бесконечности.

Для разрыва этой цепочки бесконечных вызовов поле NormalMember может инициализироваться разве что с помощью аргумента конструктора или при помощи сеттера. Для поддержки кода с 3 аргументами конструктора придётся вызвать конструктор с 4-ма аргументами и инициализировать указанное поле null-ом, иначе получится аналогичное зацикливание:

class NormalMember extends Member {
    NormalMember myChildMember;

    public NormalMember(NormalMember child, String pName, int pMemberID, int pMemberSince) {
        super (pName, pMemberID, pMemberSince);
        this.myChildMember = child;
        out.println("Fixed Child Constructor");
    }

    public NormalMember(String pName, int pMemberID, int pMemberSince) {
        this (null, pName, pMemberID, pMemberSince);
        out.println("Child Constructor with 3 params");
    }
}

Связанный вопрос: Порядок инициализации класса (конструкторов) родителя и наследника при нескольких конструкторах в обоих классах