5

有一个代码是作为初级 Java 开发人员的任务给出的。我在五年内使用 Java,这段代码让我完全困惑:

public class Main {

    String variable;

    public static void main(String[] args) {
        System.out.println("Hello World!");
        B b = new B();
    }

    public Main(){
        printVariable();
    }

    protected void printVariable(){
        variable = "variable is initialized in Main Class";
    }
}

public class B extends Main {

    String variable = null;

    public B(){
        System.out.println("variable value = " + variable);
    }

    protected void printVariable(){
        variable = "variable is initialized in B Class";
    }
}

输出将是:

Hello World!
variable value = null

但是,如果我们更改String variable = null;为,String variable;我们将拥有:

Hello World!
variable value = variable is initialized in B Class

第二个输出对我来说更清楚。因此,据我所知,Java 中的初始化顺序如下:

  • 当我们来到这个根父类时,我们转到类层次结构的根(对于 Java,它始终是 Object 类):
    • 初始化所有静态数据字段;
    • 执行所有静态字段初始化器和静态初始化块;
    • 初始化所有非静态数据字段;
    • 执行所有非静态字段初始化器和非静态初始化块;
    • 执行默认构造函数;
  • 然后我们对底层子类重复该过程。

还有一篇文章描述this了超类上下文中关键字的行为 - Calling base class overridden function from base class method

根据上面给出的规则,我假设有这样的顺序:

  1. 我们将创建一个新的 class 实例B
  2. 我们去零件课Main
  3. 初始化main.variable为空;
  4. 然后我们转到 class 的默认构造函数Main
  5. 构造函数调用b.printVariable()类中的方法Main;(为什么不调用main.printvariable?我们这里没有this关键词。)
  6. 字段b.variable变量在 B 类中初始化
  7. 现在我们回到课堂B
  8. 我们应该用空值初始化字段b.variable,对吗?
  9. B执行的类的默认构造函数

请有人可以完整而完整地解释这个继承初始化序列是如何工作的。以及为什么更改String variable = null;String variable;会导致另一个输出。

4

3 回答 3

9

顺序是:

  1. 主要->“你好”
  2. 主 -> 新 B()
  3. B() -> Main() -> b.printVariable() -> 设置变量
  4. 回到初始化 B,所以 variable=null 发生。

所以基本上,超级对象 Main() 是在 B 类的任何初始化事件之前构造的。这意味着 variable=null 稍后发生。这是有道理的,否则 B 可能会破坏 Main 的初始化。

Joshua Bloch 在他有效的 Java 书籍中涵盖了很多好的基础,关于正确的继承是多么危险,我会推荐它。

于 2013-02-25T17:57:45.913 回答
2

首先,您需要了解,当您编写variable = null;. 该代码何时执行。这基本上决定了输出。

在开始之前,我还要提一下,当你创建 的对象时class BprintVariable()不会调用主类的函数。相反,总是printVariable()会调用 B 的。

牢记这一点,当您拥有 时variable = null,B 的构造函数的执行将开始。首先Main()将被调用,它将调用 printVariable() 方法。最后,variable=null, 将被称为覆盖variable变量。

在另一种情况下,如果您不进行初始化variable=null,则variable该函数的集合printVariable()不会被覆盖,因此您会得到您所期望的。

总之,这是执行语句的顺序,当您执行以下操作时new B()

Main()     //super constructor
  B#printVariable()
  initializtion of variables in B's constructor (if any) [i.e. variable=null, if present]
于 2013-02-25T17:54:48.153 回答
1

这是一个很好的练习!但问初级开发人员并不是一个公平的问题。这个是给老年人的。但是为了让这段文字在技术面试中有用,我通过在 Main 的构造函数中添加一个参数来修改它:

public Main(String something){
 printVariable();
}

如果这个人会回答将要发生的事情,那么删除论点并提出最初的问题。如果这个人不回答 - 没有必要继续 - 他/她是初级。

您还可以删除 B 类中受保护的限定词,并询问如果您的目标是不雇用此人会发生什么:)

于 2013-02-26T01:27:34.800 回答