gpt4 book ai didi

java - 为什么这些字段在首次使用之前没有被初始化?

转载 作者:行者123 更新时间:2023-12-01 21:08:22 25 4
gpt4 key购买 nike

当我发现Java中的字段初始化有一些奇怪的顺序时,我感到非常困惑。init() 结果被字段初始化覆盖时的示例代码:

public abstract class Parent {

public String parentField = "dupa";

public Parent(){
init(); // uhh, bad practice to call abstract method in a super constructor
}

protected abstract void init();
}

public class Child extends Parent {

public String childField = null; // assigning null is unnecessary, another bad practice

@Override
protected void init(){
childField = "initialized";
System.out.println("After init(): " + childField);
}
}

...

Child child = new Child(); // OUTPUT: After init(): initialized
System.out.println("After all: " + child.childField); // OUTPUT: After all: null

我发现调用new Child();时的执行顺序是什么:

  1. 父字段初始化,但 childField 已存在且具有默认值 (childField = null)
  2. 父构造函数
    • 由父构造函数调用的重写 init() (childField = "initialized")
  3. 子字段初始化:childField = null(再次)
  4. 子构造函数

我知道这个例子充满了不好的做法。然而,对我来说直观的顺序是:字段初始化(从父级到子级),然后是构造函数(从父级到子级)。

这样的初始化命令的目的是什么?为什么字段初始值设定项在首次使用之前不执行?如果该字段还没有初始化,那为什么允许使用它呢?

最佳答案

让我解释一下您构建新对象的“直观”顺序:

  1. 父级字段已初始化
  2. 子字段已初始化
  3. 调用父级的构造函数
  4. 调用子级的构造函数

嗯,这并不是很合理,因为子字段的初始化可能依赖于父字段。

当对象的构造函数返回时,可以将其视为“正确初始化”。同意吗?

我们不使用 ParentChild,而是使用 BoxTreasureBox。要构造一个 TreasureBox,首先要制作一个 Box。创建盒子后,您可以为其添加不同的装饰,使其看起来非常漂亮和酷,您还可以添加一把锁或诸如此类的东西。

看到了吗?这里的订单?在初始化子类之前,首先正确初始化父类是最有意义的,这意味着子类的任何初始化都必须在父类的构造函数返回之后进行。这正是 Java 正在做的事情。

子项的字段可以依赖于父项的字段。要给TreasureBox上锁,您需要找到盒子的正面,并将其放在那里。如果盒子的正面还没有创建,你怎么能在它上面加锁呢?

这里有一些代码来澄清我的意思:

class Parent {

public String parentField;

public Parent(){
parentField = "Hello";
}
}

class Child extends Parent {

public int childField = parentField.length();
}

如果 Java 使用您的“直观”顺序,则会抛出 NPE。

关于java - 为什么这些字段在首次使用之前没有被初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41911269/

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