这个Java代码块背后的原理是什么?

26

Java为什么要允许这种代码?这是出于特定的原因还是其他Java语言设计决策的副产品?难道你不能只使用构造函数来实现相同的效果吗?

class Student
{
    {
        System.out.println("Called when Student class is instantiated.");
    }
}
4个回答

48

其中一个要点是它将执行被调用的任何构造函数。如果你有几个构造函数而它们不相互调用(例如每个都想调用对应的超类构造函数),这是确保所有构造函数都执行相同代码的一种方法,而不将其放在可能在其他地方被调用的方法中。

当您编写匿名类时,它也可能会很有用 - 您不能编写构造函数,但是您可以编写初始化块。例如,我曾经看到过这种方式在JMock测试中使用。


2
匿名类的提及加分。对于初始化块来说,这绝对是我最常见的用法。 - Matt Ball
我知道不久之后Jon的答案就会登顶。因为提到在匿名类中使用而被点赞。 - James P.
3
初始化块的另一个好处是可以给final实例字段赋值。而对于从多个构造函数调用的函数来说,这是不可能做到的。 - G_H
1
@Stephan:你是在暗示不可变性是一件坏事吗?我喜欢尽可能地使用方法、类和静态/实例变量... - Jon Skeet
@Stephan:我想我们必须同意各自的观点。我发现通过不可变类型和简单接口进行组合设计要比尝试设计可变类型的继承树并以某种方式可靠地使用它们更容易。 - Jon Skeet
显示剩余7条评论

20

它被称为 初始化块

Java编译器将初始化块复制到每个构造函数中。因此,这种方法可用于在多个构造函数之间共享代码块。


太棒了。我知道块,但不知道它们可以用于构造函数。感谢您提供的信息。 - James P.

5

这被称为初始化块。在这样的代码块中,您可以执行与所有构造有关的逻辑,并且还可以分离同一字段的声明初始化

更新:当然还有双括号初始化,比如

List<Integer> answers = new ArrayList<Integer>(){{add(42);}}

"Double brace initialization"与@Jon提到的内容相同:在匿名类中使用初始化块。 - Matt Ball

5

这是一个初始化块。正如Matt Ball所提到的,它们会被复制到每个构造函数中。

您可能会对静态初始化块感兴趣(也在Matt的链接中):

public class Foo {
    static {
        System.out.println("class Foo just got initialized!");
    }

    {
        System.out.println("an instance of Foo just got initialized!");
    }
}

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