Страницы

Поиск по вопросам

воскресенье, 29 декабря 2019 г.

К вопросу о конструкторах в языке программирования Java [закрыт]

#java #классы #объекты #наследование #конструктор


        
             
                
                    
                        
                            Закрыт. Данный вопрос необходимо конкретизировать. Ответы
на него в данный момент не принимаются.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Переформулируйте вопрос,
чтобы он был сосредоточен только на одной проблеме, отредактировав его.
                        
                        Закрыт 1 год назад.
                                                                                
           
                
        
Возник достаточно интересный вопрос, на который я пока не смог найти ответ, но уверен,
что здесь мне помогут. 

Все мы прекрасно знаем о том, что при создании экземпляра класса в памяти у нас осуществляется
вызов конструктора, после чего будет создан сам объект. Выполнение кода внутри конструктора
сопряжено с инициализацией полей нашего объекта (не статические поля) и вызовом одного
из родительских конструкторов (в том случае, если мы не вызываем другой конструктор
из того же класса при помощи ключевого слова this). Вот тут мы и подходим к сути вопроса.
Допустим, что у нас имеется какой-нибудь произвольный класс, который не наследуется
явным образом от какого бы то ни было существующего класса. Что это для нас означает
в плане наследования? Это означает то, что класс будет наследоваться напрямую от корневого
класса (пусть даже неявно), которым в языке программирования Java является класс Object.
Меня немного смущает тот факт, что в нашем произвольном классе мы можем описать конструктор
с любым количеством и типами входных параметров (их порядок в коде также может быть
каким угодно), в то время, как в самом классе Object имеется всего лишь один единственный
конструктор, который не принимает никаких параметров. 

Собственно сам вопрос. Происходит ли вообще обращение к конструктору класса Object?
Если да, то значит ли это, что всё время вызывается один и тот же конструктор, который
не принимает никаких параметров на вход? Или же на основании конструктора наследника
автоматически создаётся аналогичный по набору входных параметров конструктор, только
уже для класса Object? Да и вообще, правильно ли я понимаю, что при вызове конструктора
у класса Object уже не идёт вызов конструктора суперкласса, как это происходит со всеми
другими классами (по той простой причине, что класс Object является корневым классом
и является единственным классом в языке программирования Java, который не имеет предков,
как прямых, так и косвенных)?

Буду благодарен всем, кто поможет хоть как-то прояснить данную ситуацию! :)
    


Ответы

Ответ 1



Происходит ли вообще обращение к конструктору класса Object? Да, это прописано в спецификации Java (§8.8.7. Тело конструктора): If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments. Если тело конструктора не начинается с явного вызова конструктора [this или super] и заданный конструктор не является частью первоначального класса Object, то тело конструктора неявно начинается с вызова конструктора суперкласса super(); — выполнения конструктора без аргументов непосредственного класса-предка Также в п. §8.8.9 указывается, что у каждого класса есть конструктор по умолчанию, даже если он не указан явно. Это означает, что такой код: class Test { } эквивалентен такому: class Test { Test() { super(); //вызов конструктора Object } } И конструктор класса, который наследуется от Object будет вызывать конструктор Object. ... правильно ли я понимаю, что при вызове конструктора у класса Object уже не идёт вызов конструктора суперкласса, как это происходит со всеми другими классами (по той простой причине, что класс Object является корневым классом и является единственным классом в языке программирования Java, который не имеет предков, как прямых, так и косвенных)? Правильно понимаете. Предков у Object нет, и конструкторы вызывать не у кого. Для него явно сделано исключение в спецификации. Пример Для ясности предлагаю рассмотреть что именно происходит на простом примере. Возьмем следующий код: public class Test { public static void main(String[] args) { new Test(); new Object(); } } Сохраним его в файл (Test.java) и скомпилируем. Затем посмотрим какой байт-код сгенерировал компилятор (декомпилировать класс можно с помощью команды javap -c Test.class): Compiled from "Test.java" public class Test { //У класса появился конструктор public Test(); Code: 0: aload_0 //Который вызывает Object."" (super()) 1: invokespecial #1 // Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: new #2 // class Test 3: dup //При создании объекта прописывается вызов конструктора (test."") 4: invokespecial #3 // Method "":()V 7: pop 8: new #4 // class java/lang/Object 11: dup 12: invokespecial #1 // Method java/lang/Object."":()V 15: pop 16: return } По инструкциям видно, что: Компилятор явно определяет для класса: (1) конструктор по-умолчанию (2) вызов конструктора родителя. Конструкторы на данном этапе не что иное как обычные методы, которые вызываются через invokespecial и которым даны названия недопустимые в Java (""), чтобы они не пересекались с другими методами. Конструкторы (в том числе и Object) и специальные правила, относящиеся к ним, в основном существуют только на этапе компиляции. Компилятор их проверяет, обрабатывает и преобразовывает в явные инструкции вызова методов. Выполняет инструкции в байт-коде виртуальная машина Java. Именно она определяет что произойдет при вызове invokespecial Test."" и invokespecial Object."". Разработчики виртуальных машин имеют большую свободу интерпретации этих инструкций и применяют сложные алгоритмы оптимизации выполнения кода и выделения памяти.

Ответ 2



При создании объекта всегда вызывается конструктор суперкласса. Если в конструкторе вы явно не указываете какой конструктор супер класса будет вызван, то вызовется конструктор по умолчанию (без параметров), но имей те в виду если вы создали в суперклассе конструктор с параметрами, то вам придётся определить и конструктор без параметров явно т.к. он уже будет не виден. Т.е. определив конструктор с параметрами в суперклассе и не определив в нем конструктор без параметров вы не сможете в наследнике создать объект и не указать в его конструкторе super(params) т.к. получите ошибку: в суперклассе отсутствует конструктор по умолчанию. На счёт класса Object вы правильно понимаете конструирование любого класса заканчивается на конструкторе класса Object. Конструктор вызывается один и тот же. Параметры в вашем конструкторе нужны только вашему классу т.к. он (конструктор) инициализирует ваши переменные о которых суперкласс ничего не знает, соответственно и передавать ему их не надо. А вот если в суперклассе есть инициализируемые поля, то необходимо явно вызывать его конструктор с параметрами. Конструктора создаются один раз.

Ответ 3



Происходит ли вообще обращение к конструктору класса Object? Конечно происходит, поскольку в каждом классе есть конструктор, заданный явно или не явно. значит ли это, что всё время вызывается один и тот же конструктор, который не принимает никаких параметров на вход? Конструктор родительского класса вызывается независимо от того используете вы конструктор с параметрами или без. правильно ли я понимаю, что при вызове конструктора у класса Object уже не идёт вызов конструктора суперкласса Нет, неправильно. Сначала вызывается конструктор суперкласса, а потом конструктор подкласса. Если в классе есть конструктор, то он вызывается - если нет, то создаётся конструктор по умолчанию, который тоже вызывается, но вы этого не видите.

Комментариев нет:

Отправить комментарий