102

我正在查看下面的代码,发现有些奇怪:

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }

    {
        System.out.print("y ");
    }

    public static void main(String[] args) {
        new Sequence().go();
    }

    void go() {
        System.out.print("g ");
    }

    static {
        System.out.print("x ");
    }
}

我本以为这会产生编译错误,因为System.outwith "y" 不属于方法声明,只是{ }. 为什么这是有效的?我不知道如何或应该调用此代码。

运行它时它x y c g也会产生,为什么static { }在序列构造函数之前调用 get ?

4

8 回答 8

149

这:

static {
    System.out.print("x ");
}   

是一个静态初始化块,在类加载时调用。你可以在你的类中拥有任意数量的它们,它们将按照它们的出现顺序(从上到下)执行。

这:

{
   System.out.print("y ");
}

是一个初始化块,代码被复制到类的每个构造函数的开头。因此,如果您的类有许多构造函数,并且它们都需要在开始时做一些共同的事情,那么您只需编写一次代码并将其放入像这样的初始化块中。

因此,您的输出非常有意义。

正如Stanley在下面评论的那样,有关更多信息,请参阅Oracle 教程中描述初始化块的部分。

于 2012-12-04T08:56:24.853 回答
25

它不是一个方法,而是一个初始化块

{
    System.out.print("y ");
}

它将在构造函数调用之前执行。尽管

static {
    System.out.print("x ");
}

是类加载器加载类时执行的静态初始化块。

所以当你运行你的代码时

  1. 类由类加载器加载,因此执行静态初始化块
    输出:x 被打印
  2. 创建对象,因此执行初始化块,然后调用构造函数
    输出:打印 y 后跟 c
  3. 调用 main 方法,然后调用 go 方法
    输出:g 被打印

最终输出:xycg
这可能会有所帮助http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/

于 2012-12-04T08:56:35.063 回答
16

这是一个实例初始化块,后跟一个静态初始化块

{
    System.out.print("y ");
}

当您创建类的实例时被调用。

static {
    System.out.print("x ");
}

当类被类加载器加载时被调用。所以当你这样做时

new Sequence().go();

类被加载,所以它执行static {},然后它执行实例初始化块{},然后调用构造函数的主体,然后是新创建的实例上的方法。因此输出x y c g

于 2012-12-04T08:57:16.913 回答
15
static {
        System.out.print("x ");
    }

是一个静态块,在类加载期间被调用

{
    System.out.print("y ");
}

是一个初始化块

您可以在一个类中有多个初始化块,在这种情况下,它们会按照它们在类中出现的顺序执行。

请注意,类中存在的任何初始化块都在构造函数之前执行。

于 2012-12-04T08:58:36.237 回答
10
static {
      System.out.print("x ");
}

是一个由类共享的初始化块(如 所示static),它首先被执行。

{
        System.out.print("y ");

}

是一个由类的所有对象(构造函数)共享的初始化块,接下来是。

Sequence() {
        System.out.print("c ");
}

是该类的特定构造函数,第三个执行。每次执行构造函数时都会首先调用实例初始化块。这就是为什么“y”出现在“c”之前的原因。

void go() {
        System.out.print("g ");
}

只是一个实例方法,它与使用上面的构造函数构造的对象相关联,后者位于最后。

于 2012-12-04T09:04:59.040 回答
9
{
    System.out.print("y ");
}

这些类型的块称为initializer block. 每次创建class. 在编译时,此代码被移动到类的每个构造函数中。

static initializer块的情况下: -

static {
    System.out.println("x ");
}

它在加载类时执行一次。我们一般static在初始化一个字段的时候使用initializer block static,需要多个步骤。

于 2012-12-04T08:57:29.890 回答
6

它用作初始化块并在任何静态声明之后运行。与Singleton设计模式一样,它可用于确保没有其他人可以创建类的实例(与使用私有构造函数的方式相同) 。

于 2012-12-04T08:59:01.710 回答
3
static {
    System.out.print("x ");
}

Static blocks仅在 JRE加载和初始化类时执行一次。

每次创建新实例non-static时都会调用块,并且会在构造函数之前调用它。

在这里,您只创建了 1 个Sequence如此构造的实例,已在non-static块之后调用,然后是实际目标的方法。

于 2012-12-04T08:56:19.470 回答