Why instance variables get initialized before constructor called?

后端 未结 2 1700
野趣味
野趣味 2020-12-14 09:56

I have this following piece of code:

public abstract class UCMService{
    private String service;     

    protected DataMap dataMap = new DataMap(); 

            


        
相关标签:
2条回答
  • 2020-12-14 10:34

    Short answer:
    Because the spec says so.

    Long answer:
    It would be very strange for the constructor to be unable to use inline-initialized fields.

    You want to be able to write

    SomeService myService = new SomeService();
    public MyConstructor() {
        someService.doSomething();
    }
    
    0 讨论(0)
  • 2020-12-14 10:40

    This is because at compile time, the compiler moves every initialization you have done at the place of declaration to every constructor of your class. So the constructor of UCMService class is effectively compiled to:

    public UCMService(String service){
        super();  // First compiler adds a super() to chain to super class constructor
        dataMap = new DataMap();   // Compiler moves the initialization here (right after `super()`)
        System.out.println("2222");
        this.service = service;
    }
    

    So, clearly DataMap() constructor is executed before the print statement of UCMService class. Similarly, if you have any more constructor in your UCMService class, the initialization will be moved to all of them.


    Let's see the byte code of a simple class:

    class Demo {
        private String str = "rohit";
    
        Demo() {
            System.out.println("Hello");
        }
    }
    

    compile this class, and execute the command - javap -c Demo. You will see the following byte code of constructor:

    Demo();
        Code:
           0: aload_0
           1: invokespecial #1   // Method java/lang/Object."<init>":()V
           4: aload_0
           5: ldc           #2   // String rohit
           7: putfield      #3   // Field str:Ljava/lang/String;
          10: getstatic     #4   // Field java/lang/System.out:Ljava/io/PrintStream;
          13: ldc           #5   // String Hello
          15: invokevirtual #6   // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          18: return
    

    You can see the putfield instruction at line 7, initializes field str to "rohit", which is before the print statement (instruction at line 15)

    0 讨论(0)
提交回复
热议问题