Типът на връщане на конструктора в Java

1. Общ преглед

В този бърз урок ще се съсредоточим върху типа връщане за конструктор в Java.

Първо ще се запознаем с това как работи инициализацията на обекти в Java и JVM. След това ще копаем по-дълбоко, за да видим как инициализацията и присвояването на обекти работят под капака.

2. Инициализация на инстанция

Нека започнем с празен клас:

public class Color {}

Тук ще създадем екземпляр от този клас и ще го присвоим на някаква променлива:

Color color = new Color();

След компилирането на този прост фрагмент на Java, нека надникнем в неговия байт код чрез командата javap -c :

0: new #7 // class Color 3: dup 4: invokespecial #9 // Method Color."":()V 7: astore_1

Когато създаваме екземпляр на обект в Java, JVM извършва следните операции:

  1. Първо, той намира място в своето процесно пространство за новия обект.
  2. След това JVM изпълнява процеса на инициализация на системата. В тази стъпка той създава обекта в състоянието му по подразбиране. Най- новата Кодът в байткод всъщност е отговорен за тази стъпка.
  3. И накрая, той инициализира обекта с конструктора и други инициализационни блокове. В този случай invokespecial opcode извиква конструктора.

Както е показано по-горе, подписът на метода за конструктора по подразбиране е:

Method Color."":()V

The е името на методите за инициализация на екземпляра в JVM . В този случайе функция, която:

  • не приема нищо като вход (празни скоби след името на метода)
  • не връща нищо (V означава void )

Следователно типът на връщане на конструктор в Java и JVM е невалиден.

Погледнете още веднъж нашата проста задача:

Color color = new Color();

Сега, когато знаем, че конструкторът връща void , нека видим как работи заданието.

3. Как работи възлагането

JVM е виртуална машина, базирана на стека. Всеки стек се състои от рамки на стека. Казано по-просто, всеки кадър на стека съответства на извикване на метод. Всъщност JVM създава кадри с извикване на нов метод и ги унищожава, когато приключат работата си:

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

0: new #7 // class Color 3: dup 4: invokespecial #9 // Method Color."":()V 7: astore_1

Ето как работи заданието:

  • Най- новата инструкция създава инстанция на цвят и избутва своя препратка към стека на операнд
  • В мезонети Кодът дублира последния елемент на стека на операнд
  • В invokespecial отнема дублирания препратката и я изразходва за инициализация. След това в стека на операндите остава само оригиналната препратка
  • В astore_1 съхранява оригиналната препратка към индекс 1 от масива на локални променливи. Префиксът "а" означава, че елементът, който ще се съхранява, е препратка към обект, а "1" е индексът на масива

Отсега нататък вторият елемент (индекс 1) в масива от локални променливи е препратка към новосъздадения обект . Следователно, ние не губим препратката и присвояването действително работи - дори когато конструкторът не връща нищо!

4. Заключение

В този бърз урок научихме как JVM създава и инициализира нашите екземпляри на класа. Освен това видяхме как инициализацията на екземпляра работи под капака.

За още по-подробно разбиране на JVM, винаги е добра идея да проверите неговата спецификация.