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 извършва следните операции:
- Първо, той намира място в своето процесно пространство за новия обект.
- След това JVM изпълнява процеса на инициализация на системата. В тази стъпка той създава обекта в състоянието му по подразбиране. Най- новата Кодът в байткод всъщност е отговорен за тази стъпка.
- И накрая, той инициализира обекта с конструктора и други инициализационни блокове. В този случай 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, винаги е добра идея да проверите неговата спецификация.