当前位置: 首页 > 面试题库 >

Java初始化和实例化顺序

邢令
2023-03-14
问题内容

我试图将JVM中的初始化和实例化过程组合在一起,但是JLS在一些细节上有点笨拙,因此,如果有人介意清理一些细节,将不胜感激。到目前为止,这是我能够弄清楚的。

初始化

递归初始化该类及其接口的静态最终变量,这些变量是编译时间常数。

从递归中退出,按文本顺序处理静态块和静态字段。

实例化

  1. 递归初始化作为编译时间常数的类的最终实例变量。
  2. 按文本顺序退出递归处理非静态块和实例字段,并在返回时将它们放在构造函数之前。

好的,现在提出问题。

  1. 接口是否按声明顺序处理?
  2. 接口是在单独的递归堆栈中处理的吗?

a)如果是,接口是在超类之前还是之后进行处理的?
b)如果是,我是否正确推断一个或另一个(接口或超类)在其他编译时常数之前初始化了其非编译时常数字段。

  1. 在此过程中,对非默认super()构造函数的调用起什么作用?
  2. 我的结论有误吗?
  3. 我是否还缺少其他关键细节?

问题答案:

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

类初始化

首次访问时,通过分配编译时间常数字段,然后递归初始化超类(如果尚未初始化),然后处理静态初始化程序(包括用于非编译时静态字段的初始化程序),来初始化类或接口。常数)。

您已经注意到,类的初始化本身不会触发其实现的接口的初始化。因此,通常在第一次访问接口时通过读取不是编译时间常数的字段来初始化接口。这种访问可能在初始化器评估期间发生,从而导致递归初始化。

还值得一提的是,初始化不通过访问是编译时间常数领域触发,因为这些都是在评估编译时间:

常量变量字段(第4.12.4节)的引用必须在编译时解析为常量变量的初始值设定项表示的值V。

如果此类字段是静态的,则二进制文件中的代码中不应存在对该字段的引用,包括声明该字段的类或接口。这样的字段必须始终看起来已经初始化(第12.4.2节);绝对不要遵守该字段的默认初始值(如果不同于V)。

如果这样的字段是非静态的,则除了包含该字段的类之外,二进制文件的代码中不应存在对该字段的引用。(由于接口仅具有静态字段,因此它将是一个类,而不是一个接口。)该类应具有在实例创建过程中将字段的值设置为V的代码(第12.5节)。

对象初始化

每当创建新对象时,都会初始化对象,通常是通过评估类实例创建表达式来进行初始化。其过程如下:

将构造函数的参数分配给此构造函数调用的新创建的参数变量。

如果此构造函数以同一个类中的另一个构造函数的显式构造函数调用(第8.8.7节)开头(使用此方法),则使用这五个步骤评估参数并递归处理该构造函数调用。如果该构造函数调用突然完成,则该过程由于相同的原因而突然完成;否则,请继续执行步骤5。

该构造函数并不以对同一类中的另一个构造函数的显式构造函数调用(使用此函数)开头。如果此构造函数用于Object以外的其他类,则此构造函数将以显式或隐式调用超类构造函数(使用super)开始。使用这五个相同的步骤来递归评估超类构造函数调用的参数和过程。如果该构造函数调用突然完成,则出于相同原因,此过程也会突然完成。否则,请继续执行步骤4。

执行此类的实例初始值设定项和实例变量初始值设定项,并按从左到右的顺序将实例变量初始值设定项的值分配给相应的实例变量,这些变量在文本中显示在该类的源代码中。如果执行这些初始化程序中的任何一个导致异常,则不会再处理其他初始化程序,并且该过程会因相同的异常而突然完成。否则,请继续执行步骤5。

执行此构造函数的其余部分。如果该执行突然完成,则出于相同原因,此过程也会突然完成。否则,此过程将正常完成。

正如我们在步骤3中所看到的,显式调用super构造函数的存在只是更改了调用哪个super类构造函数。



 类似资料:
  • 问题内容: 我正在尝试发现初始化发生的顺序,或者更确切地说,为什么要按此顺序进行初始化的原因。给定代码: 输出: 但是,将的声明移动到初始化块之前会产生: 而且我完全不知道为什么会以这种顺序发生。此外,如果我在的声明中消除了关键字,则init块和构造函数均不会触发。谁能帮我这个忙吗? 问题答案: 我认为您只是缺少JLS的12.4.2节,其中包括: 接下来,以文本顺序执行类的类变量初始化器和静态初始

  • 我有一个Java Spring Boot应用程序,在我的Maven pom.xml中将Flyway配置为依赖项(我有一个父pom和一个项目pom...Flyway是在我的项目pom中定义的)。 application.properties中只有几个条目: 我可以运行一个maven任务来让Flyway运行来创建/更新我的数据库,然后针对该数据库运行我的应用程序,但是我很难通过运行我的应用程序(这在p

  • 问题内容: 直观上似乎很清楚,在Java中,实例变量初始化器是按照它们在类声明中出现的顺序执行的。 在我正在使用的JDK中,似乎确实是这种情况。例如,以下内容: 打印(换句话说,y选择的默认值z)。 实际可以保证此顺序吗?我一直在浏览JLS,找不到任何明确的确认。 问题答案: 是的。 se7 JLS在12.5执行部分中介绍了实例变量的初始化顺序: … 4.执行此类的实例初始值设定项和实例变量初始值

  • 本文向大家介绍tensorflow 初始化未初始化的变量实例,包括了tensorflow 初始化未初始化的变量实例的使用技巧和注意事项,需要的朋友参考一下 今日在Stack Overflow上看到一个问如何只初始化未初始化的变量,有人提供了一个函数,特地粘贴过来共大家品鉴: 通过tf.global_variables()返回一个全局变量的列表global_vars, 然后以python列表解析式的

  • 问题内容: 下面的程序打印: 首次加载类时,首先要初始化静态块和字段,然后才初始化实例块和字段。因此,应首先初始化变量“ objectName1”和“ objectName2”,然后初始化实例变量“ list”……但输出显然与该理论相矛盾……任何人都可以解释程序行为(我不是在批评程序)。设计本身顺便说一句)? 问题答案: 静态块 按顺序 初始化(因此您可以在下面的代码中依赖上面的代码)。通过在中创