it-roy-ru.com

Почему конструктор суперкласса вызывается, когда мы объявляем объект подкласса? (Джава)

Рассмотрим этот код:

class Test {
    Test() {
        System.out.println("In constructor of Superclass");
    }

    int adds(int n1, int n2) {
        return(n1+n2);
    }

    void print(int sum) {
        System.out.println("the sums are " + sum);
    }
}


class Test1 extends Test {
    Test1(int n1, int n2) {
        System.out.println("In constructor of Subclass");
        int sum = this.adds(n1,n2);
        this.print(sum);
    }

    public static void main(String[] args) {
        Test1 a=new Test1(13,12);
        Test c=new Test1(15,14);
    }
}

Если у нас есть конструктор в суперклассе, он будет вызываться каждым объектом, который мы создаем для дочернего класса (например, объект a для класса Test1 вызывает Test1(int n1, int n2), а также его родительский объект Test()). 

Почему это происходит?

Выход этой программы:

В конструкторе Суперкласса

В конструкторе подкласса

суммы 25

В конструкторе Суперкласса

В конструкторе подкласса

суммы 29

32
aman_novice

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

см. 3.4.4 в здесь

35
Ashkan Aryan

Да. Суперкласс должен быть создан до того, как может быть создан производный класс, в противном случае некоторые поля, которые должны быть доступны в производном классе, могут быть не инициализированы.

Небольшое примечание: Если вам нужно явно вызвать конструктор суперкласса и передать ему некоторые параметры:

baseClassConstructor(){
    super(someParams);
}

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

baseClassConstructor(){
     foo(); 
     super(someParams); // compilation error
}
18
Heisenbug

super () добавляется в каждый конструктор класса автоматически компилятором.

Как мы хорошо знаем, конструктор по умолчанию предоставляется компилятором автоматически, но он также добавляет super () для первого оператора. Если вы создаете свой собственный конструктор, и у вас нет this () или super () в качестве первого оператора, компилятор предоставит super () в качестве первого оператора конструктора.

 enter image description here

8
Jaimin Patel

Классы Java создаются в следующем порядке:

(во время загрузки класса) 0. инициализаторы для статических членов и статических инициализаторов, в порядке декларации.

(на каждом новом объекте) 

  1. создать локальные переменные для аргументов конструктора
  2. если конструктор начинается с вызова другого конструктора для класса , оцените аргументы и вернитесь к предыдущему шагу. Все шаги Для этого конструктора выполнены, включая дальнейшую рекурсию вызовов конструктора , Прежде чем продолжить.
  3. если суперкласс не был создан вышеупомянутым, создайте суперкласс (используя конструктор no-arg, если не указан). Как и # 2, , Прежде чем продолжить, выполните все эти шаги для суперкласса, включая создание Это суперкласс.
  4. инициализаторы для переменных экземпляра и нестатических блоков инициализаторов, в порядке объявления.
  5. остальная часть конструктора.
3
Oh Chin Boon

Вот как работает Java. Если вы создаете дочерний объект, супер-конструктор вызывается (неявно).

2
anon

здесь расширение вашего Test до вашего класса test1, означающее, что вы можете получить доступ ко всем методам и переменным test в вашем test1. Имейте в виду, что вы можете получить доступ к методам класса или переменной, только если ему выделена память и для этого нужен какой-то конструктор, либо по умолчанию, либо с параметризацией, поэтому здесь, когда компилятор обнаруживает, что он расширяет класс, он попытается найти конструктор суперкласса, так что вы можете получить доступ ко всем его методам.

1
Akhil Vijayan

Проще говоря, если у суперкласса есть параметризованный конструктор, вам нужно явно вызвать super (params) в первой строке вашего дочернего конструктора класса, иначе неявно все конструкторы суперкласса будут называться до тех пор, пока класс объекта не будет responsehead.

1
Isham

«Если конструктор не вызывает явно конструктор суперкласса, компилятор Java автоматически вставляет вызов в конструктор суперкласса без аргументов. Если суперкласс не имеет конструктора без аргументов, вы получите ошибку во время компиляции У Object действительно есть такой конструктор, поэтому, если Object является единственным суперклассом, проблем нет ».
(источник: https://docs.Oracle.com/javase/tutorial/Java/IandI/super.html )

1
Sameer Khanal

Конструктор базового класса будет вызываться перед конструктором производного класса. Это имеет смысл, поскольку гарантирует, что базовый класс правильно сконструирован при выполнении конструктора для производного класса. Это позволяет использовать некоторые данные из базового класса при создании производного класса.

1
Ravi

Как мы знаем, переменные-члены (поля) класса должны быть инициализированы перед созданием объекта, потому что эти поля представляют состояние объекта. Если эти поля явно не инициализированы, то компилятор неявно предоставляет им значения по умолчанию, вызывая конструктор по умолчанию без аргументов. Вот почему конструктор подкласса вызывает суперкласс конструктор по умолчанию без аргументов или неявно вызывается компилятором. Локальные переменные не предоставляют значения по умолчанию компилятором.

1
maneeshp626

Когда мы создаем объект подкласса, он должен учитывать все функции-члены и переменные-члены, определенные в суперклассе. Может возникнуть случай, когда некоторая переменная-член может быть инициализирована в некоторых конструкторах суперкласса. Следовательно, когда мы создаем объект подкласса, все конструкторы в соответствующем дереве наследования вызываются сверху вниз.

В частности, когда переменная определена как protected она всегда будет доступна в подклассе независимо от того, находится ли подкласс в том же пакете или нет . Теперь из подкласса, если мы вызываем функцию суперкласса для печати значения этой защищенной переменной (которая может быть инициализирована в конструкторе суперкласса), мы должны получить правильное инициализированное значение. Поэтому все конструкторы суперкласса вызываются.

Внутренне Java вызывает super () в каждом конструкторе. Таким образом, каждый конструктор подкласса вызывает свой конструктор суперкласса, используя super (), и, следовательно, они выполняются сверху вниз.

Примечание. Функции могут быть переопределены, а не переменные. 

1
Aniket Thakur

Я постараюсь ответить на это с другой точки зрения. 

Предположим, что Java не вызывает для вас супер-конструктор автоматически. Если вы наследуете класс, вам придется либо неявно вызывать супер-конструктор, либо переписать его самостоятельно. Это потребует от вас внутренних знаний о том, как работает суперкласс, что плохо. Также потребуется переписать код, что тоже не хорошо. 

Я согласен, что вызывать супер-конструктор за кулисами немного не интуитивно. С другой стороны, я не уверен, как они могли бы сделать это более интуитивным способом. 

1
NL3294

В ваших конструкторах по умолчанию для подклассов есть вызов super () по умолчанию.

 //Default constructor of subClass
    subClass() {
    super();
    }
1
Bhaskar

Подкласс наследует поля своего суперкласса (ов) и эти поля имеют для создания/инициализации (это обычная цель конструктора: инициализировать члены класса, чтобы экземпляр работал как требуется. Мы знаем, что некоторые люди, но намного больше функциональности в этих бедных конструкторах ...)

1
Andreas_D

Поскольку вы наследуете свойства базового класса в производном классе, могут быть ситуации, когда вашему конструктору производного класса требуются некоторые переменные базового класса для инициализации его переменных. Итак, сначала он должен инициализировать переменные базового класса, а затем производные переменные класса. Вот почему Java вызывает сначала конструктор базового класса, а затем конструктор производного класса.

А также не имеет смысла инициализировать дочерний класс без инициализации родительского класса.

1
user1923551

Конструктор реализует логику, которая делает объект готовым к работе. Объект может содержать состояние в закрытых полях, поэтому только методы его класса могут получить к ним доступ. Поэтому, если вы хотите, чтобы экземпляр вашего подкласса был действительно готов к работе после вызова конструктора (т.е. все его функции, включая унаследованные от базового класса, в порядке), необходимо вызвать конструктор базового класса. 

Вот почему система работает таким образом. 

Автоматически вызывается конструктор по умолчанию для базового класса. Если вы хотите изменить это, вы должны явно вызвать конструктор базового класса, написав super() в первой строке конструктора вашего подкласса.

1
AlexR

Сначала вызывается конструктор класса Super, потому что все методы в программе сначала присутствуют в куче, а после компиляции они сохраняются в стеке, благодаря чему конструктор суперкласса вызывается первым.

1
Mukul Goyal

Родители выходят первыми !! И, как и в реальном мире, ребенок не может существовать без родителей .. Поэтому инициализация родителей (суперкласса) в первую очередь важна для использования thrm в классах детей (подкласс).

0
Shubham Soni