资料内容:
使用 new 来创建对象
使用 new 来创建对象是最简单的一种方式了, new 是 Java 中的关键字,new 通过为新对象分配内存
并返回对该内存的引用来实例化一个类,这个实例化一个类其实就相当于创建了一个对象,因为类也是
一种对象;new 也负责调用对象的构造函数,下面是使用 new 来创建对象的代码
Object obj = new Object();
这段代码中,我们在堆区域中分配了一块内存,然后把 obj 对象指向了这块内存区域。
不知道你有没有看过 new 的字节码呢?下面是这段代码的字节码
在 Java 中,我们认为创建一个对象就是调用其构造方法,所以我们使用 new Object() 构造的对象,其
实是调用了 Object 类的 无参数 的构造方法。但是通过字节码我们发现,对象的创建和调用其构造方法是分开的。
字节码的 new 表示在堆中创建一个对象,并把对象的引用推入栈中。 invokespecial 表示调用对象无
参数的构造方法。其实,JVM 提供了五种方法调用指令,分别是
invokestatic :该指令用于调用静态方法,即使用 static 关键字修饰的方法;
invokespecial :该指令用于三种场景:调用实例构造方法,调用私有方法(即 private 关键字修饰
的方法)和父类方法(即 super 关键字调用的方法);
invokeinterface :该指令用于调用接口方法,在运行时再确定一个实现此接口的对象;
invokevirtual :该指令用于调用虚方法(就是除了上述三种情况之外的方法);
invokedynamic :在运行时动态解析出调用点限定符所引用的方法之后,调用该方法;在 JDK 1.7
中提出,主要用于支持 JVM 上的动态脚本语言(如 Groovy,Jython 等)
好了,现在你知道了 new 和 invokespecial 是干啥用的,那么 dup 指令呢?
dup 会复制栈上的最后一个元素,然后再次将其推入栈;因此,如果在栈上有一个对象引用,并且调用
了 dup,则现在在栈上有对该对象的两个引用。看起来有点不知其所以然,所以在求助网上的时候,又
发现了 R 大的解释
来源:./images/52749416
后面的 astore 就会把操作数栈顶的那个引用消耗掉,保存到指定的局部变量去。
如果直接使用 new Object() 没有创建局部变量的话,请注意一下它的字节码。
看出来细微的差别了吗?上图中的 astore_1 竟然变成了 pop ,这也就是说,new Object() 没有保存对
象的局部变量,而是直接把它给消耗掉了。嗯,符合预期。
所以这是第一种创建的方式,也就是使用 new 来创建。