【问题标题】:Need info about Java construct需要有关 Java 构造的信息
【发布时间】:2016-03-10 03:42:51
【问题描述】:

我最近注意到 java 中的这种构造,它允许在构造函数被调用之前执行代码:

public class Foo {

    {
        System.out.println("before constructor 1");
    }

    public Foo () {
        System.out.println("constructor");
    }


    {
        System.out.println("before constructor 2");
    }

}

有了这个类,当构造函数被调用时:

new Foo();

这得到输出:

before constructor 1
before constructor 2
constructor

我想了解更多关于这个结构的信息:它是如何被调用的,何时添加的,文档页面 url ...

【问题讨论】:

标签: java constructor


【解决方案1】:

这是instance initialiser block

编译器按照给定的顺序连接类中的所有实例初始化程序块,然后将结果复制到所有构造函数的开头,包括隐式无参数之一(如果适用)。

只有当你有一个超类的构造函数调用时,这些语义与你只是将这段代码复制到构造函数中不同。实例初始化器允许您在调用 super() 之前运行代码,但语言规则不允许您使用此属性编写构造函数。

类似的机制用于处理字段初始化器。当你像这样定义一个字段时:

int something = 3;

它将生成something = 3 并将其复制到每个构造函数的开头(任何实例初始化程序之前)。

static initialiser blocks也很有趣

【讨论】:

  • 你的回答有一个错误——如果你有一个匹配超级的构造函数,父构造函数调用必须是构造函数的第一行。在构造函数之前执行代码的唯一方法是使用此实例初始化程序块。
  • 实例初始化程序块只是被编译器复制到每个构造函数的开头。在您编写的每个构造函数的开头调用 super 的需要是与此机制无关的语言规则。我将明确提及这一点,因为这是唯一一种语义实际上与到处复制粘贴代码不同的情况。
  • 这些 cmets 的意思是这些块不会在构造函数之前执行 - 它们在构造函数的开头执行,在构造函数中的其余语句执行之前执行,类似于实例变量的执行方式被初始化。这很容易看到——即使没有这样的块——当使用调试器时,进入构造函数。
  • 是的。这正是我的回答所说的。编译器确实将这些块复制到所有构造函数中
  • 没有神奇的“在构造函数之前”的地方让代码运行,只有这个方便的简写可以让代码在所有构造函数中结束。完全相同的机制用于实例变量初始化器:但我在上面说了所有这些。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
  • 1970-01-01
相关资源
最近更新 更多