调用不带名称的Java方法


100

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

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.out带有“ y”的不仅仅属于方法声明{ }。为什么这样有效?我不知道如何或应该调用此代码。

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

Answers:


148

这个:

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

是一个静态初始化块,并在加载类时调用。您可以根据需要在类中添加任意数量的对象,它们将按照其出现顺序(从上到下)执行。

这个:

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

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

因此,您的输出非常合理。

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



6
the code is copied into the beginning of each constructor of the class-这是不正确的。假设构造函数以开头super("x ");,超级构造函数将在任何初始化块之前执行。
RokL 2012年

3
是的,将先执行对超级构造函数的隐式和显式调用,然后执行初始化块,然后再执行其余的构造函数代码。
jlordo

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/


@克苏鲁:谢谢。有效期到上周,我已使用新链接对其进行了更新。
xyz 2012年

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

这些类型的块称为initializer block。每次您创建一个实例时都会执行class。在编译时,此代码被移到类的每个构造函数中。

如同static initializer封锁的情况:-

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

加载该类后,它将执行一次。我们通常static在初始化static字段时使用初始化程序块,需要多个步骤。


6

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


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

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

non-static块将调用你正在创造一个新的实例每次,这将是刚刚构造函数之前调用。

到这里为止,您仅创建了1个Sequence这样构造的实例,该实例在non-static块之后调用,然后才是实际目标的方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.