好的,所以我正在学习我的第一个java认证,我不能完全理解在创建一个对象时底下发生了什么,一些解释说明了这些解释说明构造函数返回对象的引用,这对我来说是一个混乱的根源,因为根据我的理解,这是由new关键字完成的。我的问题是:
答案 0 :(得分:0)
new Constructor(arguments)
的整个表达式被认为是一个实例创建表达式,并且作为单独的new
关键字和构造函数调用没有意义。
JLS,15.9.4描述了实例的实际创建,它包含三个步骤:
new
时不适用)首先,如果类实例创建表达式是限定类 实例创建表达式,限定主表达式是 评估。如果限定表达式的计算结果为null,则a 引发NullPointerException,并创建类实例 表达突然完成。如果符合条件的表达式完成 突然,类实例创建表达式突然完成 出于同样的原因。
接下来,为新的类实例分配空间。如果有 没有足够的空间来分配对象,评估类 实例创建表达式通过抛出一个突然完成 的OutOfMemoryError。
新对象包含声明的所有字段的新实例 指定的类类型及其所有超类。作为每个新领域 实例创建后,会初始化为默认值(§4.12.5)。
接下来,计算构造函数的实际参数, 左到右。如果任何参数评估突然完成, 不评估其右边的任何参数表达式和类 由于同样的原因,实例创建表达式突然完成。
接下来,调用指定类类型的选定构造函数。 这导致为每个超类调用至少一个构造函数 类类型。这个过程可以通过显式指导 构造函数调用语句(第8.8节)并详细说明 §12.5。
类实例创建表达式的值是对它的引用 新创建的指定类的对象。每一次 在评估表达式时,会创建一个新对象。
是的,作为字节码,这一切都变成了一个invokespecial调用,新实例位于传递的参数堆栈的底部。请参阅此答案的底部。但是,在语义上,构造函数不会将新实例“传递”给它,但该实例在Java源代码中以this
形式提供。
我编译和反汇编:
class Test{
public static void main(String args[]){
Integer s = new Integer(2);
}
}
结果如下:
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/lang/Integer
3: dup
4: iconst_2
5: invokespecial #3 // Method java/lang/Integer."<init>":(I)V
8: astore_1
9: return
如您所见,首先使用new
分配对象,该对象将所有字段填入默认值。它是重复的,所以堆栈看起来像:
our new Integer
our new Integer
然后推送我传递给构造函数的常量值:
2
our new Integer
our new Integer
发生 invokespecial
,它传递顶部的两个堆栈元素 - 新实例和构造函数的参数。