8

我有我无法理解的代码,它如何产生该输出。这是下面的代码 -

代码:

class Bird {
  { System.out.print("b1 "); }
  public Bird() { System.out.print("b2 "); }
}
class Raptor extends Bird {
  static { System.out.print("r1 "); }
  public Raptor() { System.out.print("r2 "); }
  { System.out.print("r3 "); }
  static { System.out.print("r4 "); }
}
class Hawk extends Raptor {
  public static void main(String[] args) {
    System.out.print("pre ");
    new Hawk();
    System.out.println("hawk ");
  }
}

输出:

r1 r4 pre b1 b2 r3 r2 hawk

问题:

我关于此代码的具体问题是 -

  1. Hawk类被安装时,它会导致Raptor类被安装,因此静态代码块首先运行。但是,在打印之前,静态代码应该跟在非静态代码之后pre。不是吗?
  2. 那些非静态初始化块似乎实际上就像构造函数一样。那么,这些可以用作常规编程中的构造函数吗?
4

4 回答 4

7

在打印 pre 之前,静态代码后面应该跟非静态代码。不是吗?

  1. 运行Hawk.main会触发所有三个类的初始化。这是静态初始化程序运行的时间;
  2. pre已打印;
  3. new Hawk()触发所有三个类的实例初始化程序的执行。

这些可以用作常规编程中的构造函数吗?

它们最终与构造函数中的代码一起编译成<init>方法。所以是的,它们类似于构造函数代码。关键区别在于,无论哪个构造函数运行,它们都会运行,并且在构造函数主体之前运行。

于 2013-06-07T13:04:29.063 回答
3

这些static块在加载类时运行,因此它们甚至在您的方法运行之前main()运行。

初始化程序块在构造函数之前运行。构造函数和初始化块之间的区别在于构造函数可以有参数。

另请注意,初始化程序块和构造函数首先在基类中运行,然后在子类中运行。

于 2013-06-07T13:04:52.197 回答
0

1 - 先打印 pre,因为实际上只有在运行 new Hawk() 时才创建 Hawk,直到那一刻,才会执行静态初始化程序。

2 - 非静态初始化通常用于初始化变量的值,但由于您无法将参数传递给它们,因此与构造函数相比,您不太可能实现相同的目标。在这些块中,您可以将属性初始化为常量值或空值。

于 2013-06-07T13:05:09.350 回答
0
  1. 静态初始化器首先运行(实际上是按照定义的顺序)
  2. 您可以使用初始化程序块,但在声明或构造函数中初始化字段是一种常见的习惯用法。

Java 教程对此进行了详细记录。

于 2013-06-07T13:08:02.863 回答