【问题标题】:How is it possible for variables to be initialized outside of the constructor?如何在构造函数之外初始化变量?
【发布时间】:2017-05-12 03:12:51
【问题描述】:

变量只在对象创建期间获得内存分配,那么为什么在构造函数之外为变量赋值不会产生错误呢?此外,由于没有创建特定对象,因此该分配值的位置是什么?

【问题讨论】:

  • 字段初始化器在构造函数的主体之前运行,仅此而已。请注意,内存分配本身只发生一次,在 any 构造函数执行之前。
  • 下次见到James Gosling 时,你会问他为什么选择这种语言。
  • 为什么我的问题被搁置了? @波西米亚。我不是问为什么这个规则在 JAVA 中,只是想知道初始化值的位置是什么?请在暂停之前尝试理解我的问题。
  • @Rony 不,你的标题问为什么。这是基于意见的,因为您本质上是在问为什么语言设计者会做出这个决定。你必须让他们找出答案。各种初始化形式的效果都在JLS中有明确记载。
  • 我已经对其进行了重构,希望现在它不会出现任何问题。 @波西米亚

标签: java constructor instance-variables


【解决方案1】:

因为所有实例字段初始化代码(以及任何实例初始化块)都像构造函数的一部分一样被执行。

变量只在对象创建期间获得内存分配

其实顺序如下:

  1. 评估构造函数参数表达式。
  2. 如果尚未执行类初始化,请执行它。 (这在类的生命周期中发生一次......)
  3. 为对象分配内存,包括类和超类链的实例字段的内存。
  4. 执行默认初始化字段。
  5. 执行this(...)super(...) 呼叫。 (这会递归执行字段初始化和运行构造函数的链。对于this 调用,我们将跳过下一步。)
  6. 按源代码顺序执行类实例字段初始化程序和静态初始化程序块。
  7. 执行构造函数的剩余部分。
  8. 如果这是叶构造函数,则返回构造的对象。否则展开一层递归。

第 6 步是处理您关心的字段初始值设定项的地方。初始化表达式和块的代码组合成一个合成方法,构造函数在适当的位置调用该方法。但是,这是一个实现细节。

如您所见,分配给对象的内存量很早就确定了,不受任何初始化逻辑的影响。在对象本身中表示它们所需的变量和内存量将是相同的......无论如何。

此外,由于没有创建特定对象,因此该分配值的位置是什么?

字段的位置是在步骤 3 中分配的对象的一部分。就像在构造函数中完成初始化的情况一样。

(也许您对将对象或数组分配给字段时实际发生的情况感到困惑?请记住,对象和数组类型称为引用类型。类型为引用的字段或变量类型对应于一个位置来保存只是引用...而不是引用所引用的对象的实际状态。)

(也许您认为构造函数的调用与普通方法的调用相同。事实并非如此......见上文。)

【讨论】:

    猜你喜欢
    • 2012-06-30
    • 1970-01-01
    • 2020-09-27
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    • 2014-08-23
    相关资源
    最近更新 更多