让我们测试如何编译这些类。
public class Test1 {
private Scanner in;
public Test1() {
in = new Scanner(System.in);
}
}
和
public class Test2 {
private Scanner in = new Scanner(System.in);
public Test2() {
}
}
如果我们使用javap -c Test1
我们会看到
Compiled from "Test1.java"
public class Test1 {
public Test1();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #12 // class java/util/Scanner
8: dup
9: getstatic #14 // Field java/lang/System.in:Ljava/io/InputStream;
12: invokespecial #19 // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
15: putfield #22 // Field in:Ljava/util/Scanner;
18: return
}
如果我们使用它,Test2
我们会得到
Compiled from "Test2.java"
public class Test2 {
public Test2();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #12 // class java/util/Scanner
8: dup
9: getstatic #14 // Field java/lang/System.in:Ljava/io/InputStream;
12: invokespecial #19 // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
15: putfield #22 // Field in:Ljava/util/Scanner;
18: return
}
所以你可以看到类中in
字段的初始化是Test2
在构造函数开始时由编译器自动移动的。
事实上,这段代码将在该类的每个构造函数的开始处移动(super()
如果有的话,在调用之后立即移动),所以唯一的区别是,如果你的构造函数很少,你可以in
在构造函数之外的一个地方初始化字段,而不是在每个构造函数中都这样做.
但是,如果假设您想根据构造函数中传递的某些参数来初始化字段,那么您必须在构造函数块中进行。