为什么实例变量在构造函数调用之前被初始化? [英] Why instance variables get initialized before constructor called?

查看:343
本文介绍了为什么实例变量在构造函数调用之前被初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

  public abstract class UCMService {
private String service;

protected DataMap dataMap = new DataMap();

protected class DataMap extends HashMap< String,String> {

private static final long serialVersionUID = 4014308857539190977L;

public DataMap(){
System.out.println(11111);
put(IdcService,service);
}
}

public UCMService(String service){
System.out.println(2222);
this.service = service;
}
}

UCMService 的构造函数之前执行 构造函数.out.println p>

我想知道为什么会发生。

解决方案

编译时,编译器将您在声明位置执行的每个初始化移动到类的每个构造函数。因此, UCMService 类的构造函数有效地编译为:

  public UCMService (String service){
super(); //首先编译器添加一个super()链接到超类构造函数
dataMap = new DataMap(); //编译器在这里移动初始化(在'super()'之后)
System.out.println(2222);
this.service = service;
}

所以,清楚 DataMap $ c>构造函数在 UCMService 类的打印语句之前执行。同样,如果你的 UCMService 类中有更多的构造函数,初始化将被移动到所有的。






让我们看一个简单类的字节码:

  
private String str =rohit;

Demo(){
System.out.println(Hello);
}
}

编译此类,并执行命令 - javap -c Demo 。您将看到以下构造函数的字节代码:

  Demo 
代码:
0:aload_0
1:invokespecial#1 //方法java / lang / Object。< init>:()V
4:aload_0
5:ldc#2 //字符串rohit
7:putfield#3 //字段str:Ljava / lang / String;
10:getstatic#4 //字段java / lang / System.out:Ljava / io / PrintStream;
13:ldc#5 // String Hello
15:invokevirtual#6 //方法java / io / PrintStream.println:(Ljava / lang / String;)V
18:return

您可以在第7行看到 putfield ,在 print 之前初始化 str rohit $ c>语句( 15 )指令


I have this following piece of code:

public abstract class UCMService{
    private String service;     

    protected DataMap dataMap = new DataMap(); 

    protected class DataMap extends HashMap<String,String> {

        private static final long serialVersionUID = 4014308857539190977L;

        public DataMap(){
            System.out.println("11111");
            put("IdcService",service);
        }
    }

    public UCMService(String service){
        System.out.println("2222");
        this.service = service;
    }
}

Now in console the System.out.println of DataMap constructor is executing before the constructor of UCMService.

I was wondering why it is happening.

解决方案

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)

这篇关于为什么实例变量在构造函数调用之前被初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆