class test {
test() {
System.out.println("Constructor");
}
{
System.out.println("Hai");
}
}
public class sample {
public static void main(String [] a) {
test t = new test();
}
}
在上面的代码中为什么大括号((即“Hai”)中给出的语句在构造函数执行之前被打印。
答案 0 :(得分:34)
让我们用一个更明确的例子来表达:
public class Test {
static {
System.out.println("static initializer");
}
{
System.out.println("instance initializer");
}
public Test() {
System.out.println("constructor");
}
}
并按如下方式进行测试:
public class Main {
public static void main(String[] args) {
Test test1 = new Test();
Test test2 = new Test();
}
}
输出:
static initializer
instance initializer
constructor
instance initializer
constructor
静态初始化程序在运行时仅执行一次,特别是在加载类时。实例初始值设定项在构造函数之前的每个实例化期间执行。
您可以拥有多个,并且它们将按照编码中的顺序执行。
实例初始化程序的主要好处是无论您使用哪种构造函数,它们都会被执行。它们适用于每一个,因此您不需要在所有这些上复制常见的初始化。
静态初始化器的主要好处是它们在类加载期间只执行一次。一个众所周知的现实世界的例子是JDBC驱动程序。当你这样做
Class.forName("com.example.jdbc.Driver");
只执行static
初始化程序,然后任何(正常的)JDBC驱动程序将在DriverManager
中注册自己,如下所示
static {
DriverManager.registerDriver(new com.example.jdbc.Driver());
}
这样DriverManager
可以在getConnection()
期间找到正确的JDBC驱动程序。
答案 1 :(得分:6)
是。这是一个instance initializer。它会在实例化后立即运行。
答案 2 :(得分:3)
在上面的代码中,为什么在执行构造函数之前,大括号((即“Hai”)中给出的语句是Printed。
因为这是12.5 Creation of New Class Instances的Java Language Specification部分所述的预期行为:)
在引用之前 创建的对象作为返回 结果,指示的构造函数是 处理以初始化新对象 使用以下程序:
- 将构造函数的参数分配给新创建的参数 此构造函数的变量 调用。
- 如果此构造函数以显式构造函数调用开头 同一个类中的另一个构造函数 (使用
this
),然后评估 参数和进程构造函数 使用这些递归调用 同样的五个步骤。如果那个构造函数 然后,调用突然完成 这个程序突然完成了 同样的原因;否则,继续 步骤5。- 此构造函数不以显式构造函数开头 调用另一个构造函数 同一个班级(使用
this
)。如果这 构造函数是用于除了之外的类Object
,然后这个构造函数会 以明示或暗示开头 调用超类构造函数 (使用super
)。评估 超类的参数和过程 构造函数调用递归 使用这五个相同的步骤。如果说 构造函数调用完成 突然,然后这个程序 为此突然完成 原因。否则,继续步骤 4。- 执行实例初始值设定项和实例变量初始值设定项 这个类,分配值 实例变量初始化器 相应的实例变量,in 他们的从左到右的顺序 在源代码中以文本形式出现 为了上课。如果执行任何 这些初始化器导致了 例外,然后没有进一步 初始化程序已处理完毕 程序突然完成 同样的例外。否则,继续 与第5步。(在一些早期 实现,编译器 错误地省略了代码 如果字段初始化字段 初始化表达式是一个常量 值等于的表达式 默认的初始化值 它的类型。)
- 执行此构造函数的其余部分。如果执行 突然完成,然后这个 程序突然完成 同样的道理。否则,这个程序 正常完成。
醇>
有关...实例初始值设定项的详细信息,请参阅8.6 Instance Initializers部分。
答案 3 :(得分:2)
类中的大括号引入了一个实例初始化器(在Java 1.1中引入)。它们的处理方式与指定作为声明一部分的字段的代码相同。所以以下是等价的:
private final Thing x = new Thing();
和
private final Thing x;
{
x = new Thing();
}
代码在调用超级构造函数后立即由构造函数执行。因此,假设没有其他初始化,代码可以作为构造函数的一部分等效地编写:
private final Thing x;
public MyCLass() {
super(); // Often implicit.
x = new Thing();
}
位于相同位置的大括号前面有static
关键字和静态初始化程序,在初始化类时执行一次,而不是基于每个实例执行。