当前位置: 首页 > 面试题库 >

为什么实例变量在构造函数调用之前被初始化?

单于皓轩
2023-03-14
问题内容

我有以下这段代码:

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;
    }
}

现在在控制台中System.out.printlnDataMap构造函数要在的构造函数之前执行UCMService

我想知道为什么会这样。


问题答案:

这是因为在编译时,编译器会将在声明位置完成的每个初始化都移到类的每个构造函数中。因此,UCMService类的构造函数可以有效地编译为:

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;
}

因此,显然DataMap()构造函数是在类的print语句之前执行的UCMService。同样,如果您的类中还有其他构造函数UCMService,则初始化将移至所有它们。

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

class Demo {
    private String str = "rohit";

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

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

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

您可以putfield在第7行看到该指令,将field初始化str"rohit",位于print语句之前(在的指令15



 类似资料:
  • 问题内容: 为什么必须在构造函数完成之前初始化最终变量? 当我编译这段代码时,我得到这样的错误 err:变量q可能尚未初始化 问题答案: 官方理由是,它是由定义的Java语言规范8.3.1.2: 必须在声明该类的每个构造函数的末尾绝对分配一个空白的最终实例变量;否则会发生编译时错误。 空白的final是其声明缺少初始化程序(即您所描述的内容)的final变量。

  • 问题内容: 我有两个班,第一个是我的主班,第二个是我的编辑框架班。 我的第二个类(UpdateGUI)在其构造函数中提供oldName,并对其进行编辑,当我单击时,它将newName发送给我的第一个类。 我的第二堂课: 我的问题是,为什么newName为null? 更新: UpdateGUIDialog类: 输出: 我需要打印而不是null。 问题答案: Java对象有点像真实对象。并顾名思义:它

  • 问题内容: 有没有在Java构造函数中使用最终变量的解决方案?问题是,如果我初始化一个最终字段,例如: 那么我就不能在构造函数中使用它。Java首先运行构造函数,然后运行字段。有没有一种解决方案可以让我访问构造函数中的final字段? 问题答案: 我不太明白你的问题。那 执行如下:

  • 问题内容: 我已经搜索了很多,并在此处给出的堆栈溢出中得到了这个答案 那说明我们可以同时使用构造函数和简单初始化 但我想要答案 但是,如果编译器自动完成构造函数初始化,为什么还要使用构造函数初始化呢! 问题答案: 构造函数的简单定义: 初始化类对象的特殊方法。始终且仅与关键字一起使用以创建类的实例。 与类的名称相同。 可以接受一个或多个参数。 没有返回值,甚至没有void。 默认构造函数不带任何参

  • 问题内容: 我有2节课: Class A: Class B: I create a Main class which just creates new A: The output I get is: 如您所见,A的构造函数在其静态初始值设定项之前被调用。 我了解它与我创建的循环依赖关系有关,但我印象中静态初始化程序应始终在构造函数之前运行。 发生这种情况的原因是什么(技术上在Java实现中)? 是