调用没有名称的Java方法

103

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

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 ");
    }
}

我本以为这会导致编译错误,因为带有"y "的System.out不属于方法声明而只是一个{ }。 为什么这是有效的? 我不明白为什么这段代码会被调用或应该被调用。

运行时它输出x y c g,为什么static { }在序列构造函数之前被调用?

8个回答

150

This:

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

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

例如:

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

是一个初始化块,代码将被复制到类的每个构造函数的开头。因此,如果您的类有多个构造函数,它们都需要在开头执行某些共同的操作,您只需要编写一次代码并将其放在像这样的初始化块中。

因此,您的输出完全合理。

正如Stanley在下面评论中提到的那样,请参见Oracle教程中描述初始化块的部分以获取更多信息。


12
好的。请查看[http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html]了解更多关于初始化块的内容。初始化块是指在类或实例创建时自动执行的代码块,可用于初始化实例变量或执行其他必要的操作。 - Stanley
6
“将代码复制到类的每个构造函数开头”这种说法是不正确的。假设构造函数以super("x ");开始,那么在任何初始化块之前都会执行超类构造函数。 - RokL
3
是的,对父构造函数的隐式和显式调用将首先执行,接下来是初始化块,然后才是剩余的构造函数代码。 - jlordo

26

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

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

这将在构造函数调用之前执行。 同时

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

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

所以当你运行代码时:

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

最终输出结果为:x y c g
这可能会有所帮助http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/


16

这是一个实例初始化块,紧接着是一个静态初始化块

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

当您创建类的实例时,将调用此方法。

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

当类被类加载器加载时,会调用此方法。因此,当您执行以下操作时

new Sequence().go();

类被加载后,它会执行 static {},接着执行实例初始化块 {},然后调用构造函数体,最终调用新创建实例的方法。因此输出结果为 x y c g


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

静态块,在类加载时调用

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

是一个初始化块

在一个类中可以有多个初始化块,它们按照在类中出现的顺序执行。

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


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

static表示的是该初始化块是被类共享的,它会最先执行。

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

}

是一个被该类的所有对象(构造函数)共享的初始化块,它紧随其后。

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

这是类的一个特殊构造函数,在执行顺序上排在第三位。每次执行构造函数时,都会首先调用实例初始化块。这就是为什么 "y" 出现在 "c" 之前的原因。

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

仅仅是与上述构造函数构造的对象相关联的实例方法,该构造函数位于最后。


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

这些块被称为初始化块。每次创建一个class实例时,都会执行它。

在编译时,该代码被移动到类的每个构造函数中。

而对于静态初始化块

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

当类被加载时,它只执行一次。通常在需要多个步骤初始化静态字段时,我们使用 static 初始化块。


6

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


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

静态块只在JRE加载和初始化类时执行一次。

非静态块将在每次创建新实例时调用,并且它将在构造函数之前调用。

因为您在这里只创建了Sequence的一个实例,所以当非静态块和构造函数被调用后,才会调用实际目标方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接