Конструктор расширенного класса вызывается дважды - PullRequest
0 голосов
/ 28 июня 2018

Для следующего кода результат будет

Я нахожусь в B, значение 0
Я в Б, значение 44
22

public class Test {
    public static void main(String[] args) {
        P b = new B();
        System.out.println(b.a);
    }

    static class P {
        public int a = 11;

        public P() {
            a = 22;
            diplay();
        }

        public void diplay() {
            System.out.println("I am in P, value is " + a);
        }
    }

    static class B extends P {
        int a = 33;

        public B() {
            a = 44;
            diplay();
        }

        public void diplay() {
            System.out.println("I am in B, value is " + a);
        }
    }
}

Во-первых, почему конструктор вызывается дважды?
Почему b.a значение 22?
Наконец, почему первое a значение 0?

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

Сначала вызывается конструктор родительского класса class P. Затем он вызывает diplay(). Поскольку вы создаете экземпляр class B B::diplay(), он называется печатью I am in B, value is 0, поскольку переменная a, определенная в B, инициализируется только значением по умолчанию 0, а a = 33 еще не выполняется. После этого выполняется a = 33, затем выполняется конструктор B и печатается I am B, value 44. Вот порядок всех этих вызовов:

Порядок звонков следующий:

1. Статические блоки * суперкласса

2. Статические блоки * класса

3.Нестатические блоки * суперкласса

4. Конструктор суперкласса

5.Нестатические блоки * класса

6.Конструктор класса

https://javacertificationroadmap.com/class-initialization-and-inheritance/

0 голосов
/ 28 июня 2018

Всякий раз, когда вы не предоставляете явный вызов конструктору суперкласса, компилятор Java вставляет неявный вызов в конструктор суперкласса по умолчанию для вас (без аргументов). Это как если бы ваш B конструктор был действительно:

public B() {
    super();
    a = 44;
    diplay();
}

Вызов конструктора суперкласса вызывает конструктор P, который вызывает diplay. Объект действительно B, поэтому при полиморфизме вызывается метод B diplay.

На данный момент у вас есть утечка вашего экземпляра подкласса, потому что он еще не полностью построен. Из-за этого B переменная a, которая скрывает * Переменная 1018 * a, еще не инициализирована, поэтому она по-прежнему имеет значение по умолчанию, 0.

Затем конструктор суперкласса P завершается, и запускается остальная часть конструктора B, который также вызывает diplay. Этот вызов видит инициализированное значение 44.

Конструктор не вызывается дважды; конструктор подкласса B неявно вызывает конструктор суперкласса P, и оба конструктора вызывают diplay.

Возвращаясь к main, вы ссылаетесь на поле a, но ссылка на переменную типа P. Полиморфизм полей отсутствует, поэтому, хотя во время выполнения объект является B, извлекается значение P *1038*, которое было инициализировано как 22.

Этот код показывает, почему вообще не очень хорошая идея

  1. утечка this экземпляра объекта до завершения конструктора и
  2. намеренно объявляет переменные в подклассе с тем же именем, что и в суперклассе.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...