gpt4 book ai didi

初始化和实例化的Java顺序

转载 作者:搜寻专家 更新时间:2023-10-30 23:02:43 26 4
gpt4 key购买 nike

我正在尝试拼凑 JVM 中的初始化和实例化过程,但 JLS 在一些细节上有点迟钝,所以如果有人介意清除一些细节,我将不胜感激。到目前为止,这是我能够弄清楚的。

初始化

  1. 递归初始化类的静态最终变量及其作为编译时常量的接口(interface)。

  2. 退出按文本顺序递归处理静态 block 和静态字段。

实例化

  1. 递归地初始化作为编译时常量的类的最终实例变量。

  2. 按文本顺序退出递归处理非静态 block 和实例字段,在返回时将它们添加到构造函数中。


好的,现在开始提问。

  1. 接口(interface)是按照声明的顺序处理的吗?

  2. 接口(interface)是否在单独的递归堆栈中处理?

    a) 如果是,接口(interface)是在父类(super class)之前还是之后处理的?

    b) 如果是,我推断一个或其他(接口(interface)或父类(super class))在其他编译时常量之前初始化其非编译时常量字段是否正确。

  3. 调用非默认 super() 构造函数在此过程中扮演什么角色?

  4. 我的结论有误吗?

  5. 我是否遗漏了任何其他关键细节?

最佳答案

区分类的初始化和对象的初始化很重要。

类初始化

类或接口(interface)在 first access 时初始化,通过分配编译时常量字段,然后递归初始化父类(super class)(如果尚未初始化),然后处理静态初始化器(包括非编译时常量的静态字段的初始化器)。

正如您所注意到的,类的初始化本身不会触发它实现的接口(interface)的初始化。 因此,接口(interface)在首次访问时被初始化,通常是通过读取一个不是编译时常量的字段。这种访问可能发生在初始化程序的评估期间,导致递归初始化。

还值得注意的是,初始化不是通过访问作为编译时常量的字段触发的,因为这些是在 compile time 处计算的。 :

A reference to a field that is a constant variable (§4.12.4) must be resolved at compile time to the value V denoted by the constant variable's initializer.

If such a field is static, then no reference to the field should be present in the code in a binary file, including the class or interface which declared the field. Such a field must always appear to have been initialized (§12.4.2); the default initial value for the field (if different than V) must never be observed.

If such a field is non-static, then no reference to the field should be present in the code in a binary file, except in the class containing the field. (It will be a class rather than an interface, since an interface has only static fields.) The class should have code to set the field's value to V during instance creation (§12.5).

对象初始化

一个对象被初始化whenever a new object is created ,通常通过评估类实例创建表达式。其过程如下:

  1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.

  2. If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.

  3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.

  4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

  5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

正如我们在第 3 步中看到的那样,对父类(super class)构造函数的显式调用的存在只是改变了调用哪个父类(super class)构造函数。

关于初始化和实例化的Java顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30376327/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com