Lets test how these classes will be compiled.
public class Test1 {
private Scanner in;
public Test1() {
in = new Scanner(System.in);
}
}
and
public class Test2 {
private Scanner in = new Scanner(System.in);
public Test2() {
}
}
If we use javap -c Test1
we will see
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
}
and if we use it on Test2
we will get
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
}
So as you can see the initialization of in
field in Test2
class was automatically moved by compiler at start of constructor.
In fact this code will be moved at start of each constructor of that class (right after super()
call if any) so only difference is that if you have few constructors you can initialize in
field in one place outside constructors instead of doing it in every one of them.
But if lets say you want to initialize field depending on some argument passed in constructor then you have to do it in constructors block.