我想到这个问题的具体用法如下,但它更加普遍.
我有一个自定义JFrame
类,也可以作为ActionListener
其组件.所以我的构造函数看起来像下面这样:
private JButton myButton; public MyCustomFrame() { super(); myButton.addActionListener(this); // ... more stuff }
我的问题是,这在幕后实际上是如何运作的?如果构造函数是"创建"引用的对象this
,那么this
在构造函数返回之前我该如何使用?代码编译和工作完全正常(据我所知),所以对象必须已经"存在"在某种意义上,但我担心这可能会导致无法预料的问题.传递一个"部分构造"的引用是否存在任何危险addActionListener()
(或者只是对它执行任何逻辑)?或者是否有一些让我安全的幕后魔术?
例如,那些没有默认值但必须由构造函数提供的东西呢?如果我已private final String SOME_VALUE;
声明,我理解这应该默认为null
,但是在构造函数中为常量提供值之前,该对象不应该完全形成.那么参考,尽管是最终的,可能会有变化的价值?
Java语言规范指定了实例创建的步骤
[...]
接下来,为新类实例分配空间.如果没有足够的空间来分配对象,则通过抛出OutOfMemoryError突然完成对类实例创建表达式的求值.
新对象包含在指定类类型及其所有超类中声明的所有字段的新实例.在创建每个新字段实例时,会将其初始化为其默认值(第4.12.5节).
接下来,从左到右评估构造函数的实际参数.如果任何参数评估突然完成,则不会计算其右侧的任何参数表达式,并且由于相同的原因,类实例创建表达式会突然完成.
接下来,调用指定类类型的选定构造函数. 这导致为类类型的每个超类调用至少一个构造函数.此过程可以由显式构造函数调用语句(第8.8节)指导,并在第12.5节中详细介绍.
因此,当调用构造函数(这是一个方法)时,您的实例存在默认值.
对于final
字段,如果您尝试访问它们,它们似乎也是默认的.例如
public class Driver { public static void main(String[] args) { new Driver(); } final int value; public Driver() { print(this); value = 3; } static void print(Driver driver) { System.out.println(driver.value); } }
将打印0.如果我能找到它,我会马上回到JLS条目.
我找不到更具体的东西,然后是上面的内容.也许在4.12.4.final
变量
最终变量只能分配一次.
您可以认为默认初始化将值设置为0或null
分配更改它.