WedX - журнал о программировании и компьютерных науках

почему вывод моего кода равен нулю?

class superclass { 
    superclass() {
        show();
    }

    void show() {
        System.out.println("three");
    }
}

class subclass extends superclass {
    int x=3;

    void show() {
        System.out.println(x);
    }

    public static void main(String ar[]) { 
         subclass s=new subclass();
    }
}

Выход: 0

По моему мнению: сначала выполняется конструктор подкласса, который затем вызывает конструктор суперкласса. Это означает, что в первую очередь должен выполниться метод show() суперкласса и вывести three, но этого не происходит. Почему?

02.07.2015

Ответы:


1

Конструктор суперкласса выполняется до инициализации любой из переменных подкласса. Таким образом, x в subclass по-прежнему равно 0 (значение по умолчанию), пока выполняется конструктор superclass. Полиморфизм все еще работает, когда метод вызывается в конструкторе, поэтому вызывается show subclass, печать x печатает 0. Это иллюстрирует опасность вызова переопределяемого метода в конструкторе — переменные могут быть еще не инициализированы. В этом случае x еще не 3 [пока.

JLS, раздел 12.5, охватывает этапы выполнения конструктора.

Непосредственно перед тем, как в качестве результата будет возвращена ссылка на вновь созданный объект, указанный конструктор обрабатывается для инициализации нового объекта с использованием следующей процедуры:

  1. Назначьте аргументы конструктора вновь созданным переменным параметрам для этого вызова конструктора.

  2. Если этот конструктор начинается с явного вызова конструктора (§8.8.7.1) другого конструктора в том же классе (используя this), тогда оцените аргументы и рекурсивно обработайте этот вызов конструктора, используя те же самые пять шагов. Если этот вызов конструктора завершается внезапно, то и эта процедура завершается внезапно по той же причине; в противном случае перейдите к шагу 5.

  3. Этот конструктор не начинается с явного вызова конструктора другого конструктора в том же классе (с использованием this). Если этот конструктор предназначен для класса, отличного от Object, то этот конструктор будет начинаться с явного или неявного вызова конструктора суперкласса (используя super). Оцените аргументы и обработайте этот вызов конструктора суперкласса рекурсивно, используя те же самые пять шагов. Если этот вызов конструктора завершается внезапно, то и эта процедура завершается внезапно по той же причине. В противном случае перейдите к шагу 4.

  4. Выполнить инициализаторы экземпляра и инициализаторы переменных экземпляра для этого класса, назначив значения инициализаторов переменных экземпляра соответствующим переменным экземпляра в порядке слева направо, в котором они появляются в текстовом виде в исходном коде для класс. Если выполнение любого из этих инициализаторов приводит к исключению, то дальнейшие инициализаторы не обрабатываются, и эта процедура завершается внезапно с тем же самым исключением. В противном случае перейдите к шагу 5.

  5. Выполните остальную часть тела этого конструктора. Если это выполнение завершается внезапно, то и эта процедура завершается внезапно по той же причине. В противном случае эта процедура завершается нормально.

(выделено мной)

Переменные инициализируются после завершения вызова конструктора суперкласса, независимо от того, является ли этот вызов явным или неявным.

02.07.2015
  • это та же ссылка, по которой я учусь. Но я не понял, почему show() подкласса выполняется в конструкторе суперкласса? 02.07.2015
  • Как я уже говорил выше, здесь работает полиморфизм. Тип среды выполнения ssubclass, поэтому конструктор superclass вызывает метод show класса subclass. 02.07.2015
  • но я не вызывал show() с помощью object s 02.07.2015
  • если я пишу s.show() , то я могу понять почему идет подкласс show() , но вот какая связь между типом s и конструктором superclass 02.07.2015
  • Когда вы создаете объект для s, это subclass. Для этого класса нет явного конструктора, поэтому компилятор Java создает неявный конструктор по умолчанию. Конструктор по умолчанию вызывает конструктор суперкласса без аргументов, который здесь superclass(). Ваш конструктор superclass() явно вызывает show(). 02.07.2015
  • и вы сказали, что s относится к типу subclass, поэтому он вызывает subclass show . Хорошо, но проблема остается той же, если я напишу superclass s=new subclass() . теперь s является типом superclass, но вывод остается таким же 02.07.2015
  • Да, вы только что продемонстрировали полиморфизм. Вызываемый метод зависит от типа среды выполнения объекта, для которого вызывается метод, а не от типа переменной. 02.07.2015
  • значит это зависит от new subclass() ?? 02.07.2015
  • да. Подробнее см. в руководстве по Java по полиморфизму. 02.07.2015

  • 2

    subclass переопределяет метод show superclass. Поэтому, когда вы создаете экземпляр subclass, выполняется метод show subclass.

    Причина, по которой он возвращает 0, а не 3, заключается в том, что он вызывается из конструктора superclass, который выполняется до инициализации переменных экземпляра subclass. Поэтому x по-прежнему содержит значение по умолчанию 0.

    02.07.2015

    3

    Как я уже говорил в прошлый раз, когда вы разместили этот вопрос, когда вы создаете объект subclass, он вызывает конструктор superclass, который вызывает дочерний метод show() (который переопределяет метод super show()) до x инициализируется значением 3 .

    Если у тебя есть

    subclass(){
       show();
    }
    

    в вашем подклассе, то он напечатает 3, потому что это вызовет метод show() после того, как x будет инициализирован до этого значения.

    Если вы хотите напечатать three, вам следует вызвать super.show() в конструкторе подкласса.

    02.07.2015
  • почему он переопределяет show() суперкласса? 02.07.2015
  • @PuspenderTanwar Поскольку вы создали объект дочернего класса, все его методы переопределяют методы суперкласса. Если это помогло, пожалуйста, выберите ответ, который помог больше всего 02.07.2015
  • если я напишу s.show() , то я могу понять, почему он будет подклассом show() , но вот какая связь между типом s и конструктором superclass 02.07.2015
  • @PuspenderTanwar Когда вы создаете объект с синтаксисом A objectName = new A();, он вызывает конструктор этого класса. Если у этого класса нет конструктора (у вашего подкласса его нет), вместо этого он вызывает конструктор родителя. Но в рамках дочернего класса. 02.07.2015
  • что подразумевается под дочерним классом 02.07.2015
  • @PuspenderTanwar под этим я подразумеваю, что, поскольку дочерний объект вызывает свой родительский конструктор, все дочерние методы будут иметь приоритет (поскольку это дочерний объект). Однако, поскольку конструктор находится в родительском классе, переменные в дочернем классе инициализируются только после вызова этого конструктора. 02.07.2015
  • @PuspenderTanwar лично я предлагаю всегда указывать конструктор. Это делает ваш код менее запутанным и предотвращает нежелательное поведение. Вы должны добавить конструктор в свой дочерний класс. 02.07.2015
  • хорошо, теперь я понял. Спасибо 02.07.2015
  • @PuspenderTanwar нет проблем, помните, если вы нашли ответ полезным, выберите этот ответ в качестве решения, чтобы те, кто сталкивается с вашими проблемами, могли знать, какой из них наиболее полезен. 02.07.2015
  • Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]