共计 1372 个字符,预计需要花费 4 分钟才能阅读完成。
家喻户晓,在 java 里是不能给构造函数写返回值的,如果在低版本的编译器定义一个结构器写上返回值可能会报错,高版本外面他就是一个一般的办法。
可是如果构造函数没有返回值,那么比方 Test t = new Test() 咱们 new 一个对象的时候是怎么赋值的呢?
构造函数有返回值吗
写一段代码测试一下:
public class Test {public Test() { }
public static void main(String[] args) {Test t = new Test();
}
}
反编译一下看看:
Code:
0: new #5 // class com/irving/utils/baidu/Test
3: dup
4: invokespecial #6 // Method "<init>":()V
7: astore_1
8: return
从反编译的后果看 4: invokespecial #7 // Method “init”: ()V,调用构造函数,V 代表 void 无返回值,那么 init 代表什么含意?
我在书里找到这样一段话:
在 Java 虚拟机层面上,Java 语言中的构造函数是以一个名为 init 的非凡实例初始化办法的模式呈现的,init 这个办法名称是由编译器命名的,因为它并非一个非法的 Java 办法名字,不可能通过程序编码的形式实现。实例初始化办法只能在实例的初始化期间,通过 Java 虚拟机的 invokespecial 指令来调用,只有在实例正在结构的时候,实例初始化办法才能够被调用拜访。
一个类或者接口最多能够蕴含不超过一个类或接口的初始化办法,类或者接口就是通过这个办法实现初始化的。这个办法是一个不蕴含参数的静态方法,名为 clinit。这个名字也是由编译器命名的,因为它并非一个非法的 Java 办法名字,不可能通过程序编码的形式实现。类或接口的初始化办法由 Java 虚拟机本身隐式调用,没有任何虚拟机字节码指令能够调用这个办法,只有在类的初始化阶段中会被虚拟机本身调用。
init 代表着虚拟机调用构造函数,当初状况很显著,构造函数返回类型是 void,那么它到底是怎么赋值的呢?
赋值探索
咱们明确一点,办法的调用过程就是栈帧入栈和出栈的过程,栈帧随着办法的调用创立,办法完结销毁。栈帧的外部蕴含局部变量表、操作数栈、动静链接等。
局部变量表示意办法调用时候的参数传递,当一个实例办法被调用的时候,第 0 个局部变量存储了以后实例办法所在对象的援用 (this),后续的其余参数传递至 1 到 N 的间断地位。
操作数栈用来筹备办法调用的参数和返回后果。
以下面测试代码的办法来看 Test t = new Test() 的调用过程:
- new 创立 Test 对象,并将其援用值压入操作数栈顶
- dup 复制栈顶数值并将复制值压入栈顶
- invokespecial 应用 dup 复制的援用并用来初始化,此时栈顶应该只有 new 创立的原始援用
- astore_1 将 new 创立的援用存入局部变量表索引为 1 的地位
- return 办法失常返回
从这个过程咱们曾经看进去了,整个过程最初咱们最终拿到了 new 之后创立的对象援用,并且保留到局部变量表中,能够供咱们持续应用。
关注公众号:java 宝典