简体   繁体   English

“ new”关键字和构造函数的工作原理

[英]How exactly does the 'new' keyword and constructors work

Ok, so i'm study for my first java certification and i can't quite understand exactly what happens underneath the hood when an object is created, some explanations that iv'e read states that the constructor returns the reference to an object which is a source of confusion for me because from my understanding this is done by the new keyword. 好的,所以我正在研究我的第一个Java认证,而且我还不太了解在创建对象时引擎盖下到底发生了什么,一些读过的解释指出,构造函数将引用返回给对象,即这让我感到困惑,因为根据我的理解,这是由new关键字完成的。 My questions are: 我的问题是:

  1. Where does the reference to an object actually come from, the 'new' keyword or the constructor? 对对象的引用实际上来自“ new”关键字还是构造函数?
  2. When an object is created using the 'new' keyword, does it implicitly pass this object to the constructor? 使用'new'关键字创建对象时,是否将其隐式传递给构造函数?
  3. When an object is created using the 'new' keyword, is it just a java Object until it is passed to the constructor eg. 当使用'new'关键字创建对象时,它只是一个Java对象,直到将其传递给构造函数为止。 Person me = new Person(); 人我= new Person(); Is this object associated with the class person as soon as it is created, or only after it has been passed to the constructor 该对象是在创建后立即与类person关联的,还是仅在将其传递给构造函数之后才与它关联的对象
  1. The entire expression of new Constructor(arguments) is considered one instance-creation expression, and is not meaningful as a separate new keyword and constructor call. new Constructor(arguments)的整个表达式被视为一个实例创建表达式,作为单独的new关键字和构造函数调用没有意义。

    The JLS, 15.9.4 describes the actual creation of the instance, which is comprised of three steps: JLS 15.9.4描述了实例的实际创建,包括三个步骤:

    1. Qualifying the expression (not applicable when using new ) 限定表达式(使用new时不适用)
    2. Allocating space for the instance in memory, and setting fields to default values. 在内存中为实例分配空间,并将字段设置为默认值。
    3. Evaluating arguments for the constructor, and calling the constructor. 评估构造函数的参数,然后调用构造函数。

    First, if the class instance creation expression is a qualified class instance creation expression, the qualifying primary expression is evaluated. 首先,如果类实例创建表达式是合格的类实例创建表达式,则对合格的主表达式进行求值。 If the qualifying expression evaluates to null, a NullPointerException is raised, and the class instance creation expression completes abruptly. 如果限定表达式的结果为null,则引发NullPointerException,并且类实例创建表达式突然完成。 If the qualifying expression completes abruptly, the class instance creation expression completes abruptly for the same reason. 如果限定表达式突然完成,则类实例创建表达式由于相同的原因突然完成。

    Next, space is allocated for the new class instance. 接下来,为新的类实例分配空间。 If there is insufficient space to allocate the object, evaluation of the class instance creation expression completes abruptly by throwing an OutOfMemoryError. 如果没有足够的空间来分配对象,则通过抛出OutOfMemoryError突然完成对类实例创建表达式的评估。

    The new object contains new instances of all the fields declared in the specified class type and all its superclasses. 新对象包含在指定类类型及其所有超类中声明的所有字段的新实例。 As each new field instance is created, it is initialized to its default value (§4.12.5). 创建每个新的字段实例时,会将其初始化为其默认值(第4.12.5节)。

    Next, the actual arguments to the constructor are evaluated, left-to-right. 接下来,从左到右评估构造函数的实际参数。 If any of the argument evaluations completes abruptly, any argument expressions to its right are not evaluated, and the class instance creation expression completes abruptly for the same reason. 如果任何一个参数求值突然完成,则不会评估其右边的任何参数表达式,并且出于相同的原因,类实例创建表达式也会突然完成。

    Next, the selected constructor of the specified class type is invoked. 接下来,将调用指定类类型的选定构造函数。 This results in invoking at least one constructor for each superclass of the class type. 这导致为类类型的每个超类调用至少一个构造函数。 This process can be directed by explicit constructor invocation statements (§8.8) and is specified in detail in §12.5. 此过程可以由显式构造函数调用语句(第8.8节)指导,并在第12.5节中详细指定。

    The value of a class instance creation expression is a reference to the newly created object of the specified class. 类实例创建表达式的值是对指定类的新创建对象的引用。 Every time the expression is evaluated, a fresh object is created. 每次对表达式求值时,都会创建一个新对象。

  2. Yes, as bytecode this all turns into one invokespecial call with the new instance at the bottom of the stack of parameters passed. 是的,因为字节码全部变为一个invokespecial调用,新实例位于传递的参数堆栈的底部。 Please see the bottom of this answer. 请参阅此答案的底部。 Semantically, however, the constructor doesn't get the new instance "passed" to it, but that instance is made available as this in Java source code. 语义,但是,构造并没有得到新的实例“传递”给它,但该实例提供的this Java源代码。

  3. This question doesn't make semantic sense, as the object doesn't "exist" to the outside world until the constructor returns. 这个问题在语义上没有意义,因为在构造函数返回之前,对象不会“存在”于外界。 If the construction terminates abruptly, the object is not actually created and available. 如果构造突然终止,则该对象实际上不会创建并且不可用。 However , in memory on an OpenJDK JVM at least, the type of the object as well as any types that it extends/implements are written to an in-memory header. 但是 ,至少在OpenJDK JVM的内存中,对象的类型以及它扩展/实现的任何类型都将写入内存标头中。 This is not guaranteed for all implementations, however. 但是,并非所有实现都可以保证。

Disassembly: 拆卸:

I compiled and disassembled: 我编译并反汇编:

class Test{
    public static void main(String args[]){
        Integer s = new Integer(2);
    }
}

This is the result: 结果如下:

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

As you can see, first the object is allocated using new , which fills in all fields as defaults. 如您所见,首先使用new分配对象,该对象将默认填写所有字段。 It's duplicated, so the stack looks like: 它是重复的,因此堆栈如下所示:

our new Integer
our new Integer

The constant value that I passed to the constructor is then pushed: 然后将我传递给构造函数的常量值压入:

2
our new Integer
our new Integer

invokespecial occurs, which passes the top two stack elements--the new instance, and the constructor's parameter. 发生invokespecial ,它传递顶部的两个堆栈元素-新实例和构造函数的参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM