如何“这个”在构造函数结束之前被引用/处理? [英] How can "this" be referenced/processed before the constructor has concluded?

查看:178
本文介绍了如何“这个”在构造函数结束之前被引用/处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想到这个问题的具体用法如下,但是更广泛。



我有一个自定义 JFrame 类也用作其组件的 ActionListener 。所以我的构造函数看起来像下面:

  private JButton myButton; 

public MyCustomFrame(){
super();
myButton.addActionListener(this);
// ... more stuff
}

我的问题是,这实际上是在幕后工作吗?如果构造函数是创建由 this 引用的对象,我如何在构造函数之前使用 this 已返回?代码编译和工作完美(根据我可以告诉),所以对象必须已经存在在某种意义上,但我担心,这可能会导致不可预见的问题。在传递一个部分构造引用到 addActionListener()(或只是执行任何逻辑与一般)有任何危险吗?还是有一些幕后的魔法发生,让我安全吗?



例如,那些没有默认值,必须由构造函数?如果我有 private final String SOME_VALUE; 声明,我理解这应该默认为 null ,但对象isn' t应该完全形成,直到该常量在构造函数内被提供一个值。那么,尽管是最终的,引用可能有变化的值吗?

解决方案

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

}

如果我能找到它,可以回到JLS条目。



我找不到任何更具体的,然后是什么。也许可以在 4.12.4。 final 变量


最终变量只能分配一次。


可以认为默认初始化将值设置为0或 null ,分配会更改它。


The specific use where I thought of this problem is as follows, but it's much more generalized.

I have a custom JFrame class which also serves as an ActionListener for its components. So my constructor looks something like the following:

private JButton myButton;

public MyCustomFrame() {
    super();
    myButton.addActionListener(this);
    // ... more stuff
}

My question is, how does this actually work behind the scenes? If the constructor is what "creates" the object which is referenced by this, how can I use this before the constructor has returned? The code compiles and works perfectly fine (as far as I can tell), so the object must already "exist" in some sense, but I'm concerned that this may cause unforeseen issues. Is there any danger in passing a "partially constructed" reference to addActionListener() (or just performing any logic with it in general)? Or is there some behind-the-curtain magic happening that keeps me safe?

For example, what about things which don't have default values and must be supplied by the constructor? If I have private final String SOME_VALUE; declared, I understand that this should default to null, but the object isn't supposed to be fully formed until the constant is supplied a value within the constructor. So would the reference, despite being final, possibly have changing values?

解决方案

That Java Language Specification specifies the steps of instance creation

[...]

Next, space is allocated for the new class instance. If there is insufficient space to allocate the object, evaluation of the class instance creation expression completes abruptly by throwing an OutOfMemoryError.

The new object contains new instances of all the fields declared in the specified class type and all its superclasses. As each new field instance is created, it is initialized to its default value (§4.12.5).

Next, the actual arguments to the constructor are evaluated, left-to-right. If any of the argument evaluations completes abruptly, any argument expressions to its right are not evaluated, and the class instance creation expression completes abruptly for the same reason.

Next, the selected constructor of the specified class type is invoked. This results in invoking at least one constructor for each superclass of the class type. This process can be directed by explicit constructor invocation statements (§8.8) and is described in detail in §12.5.

So by the time the constructor (which is a method) is invoked, your instance exists with default values.

For final fields, it appears those are defaulted as well if you try to access them. For example

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

}

will print 0. I'll be right back with the JLS entry if I can find it.

I couldn't find anything more specific then what is above. Maybe in 4.12.4. final Variables

A final variable may only be assigned to once.

You can take to mean that default initialization puts the value to 0 or null and the assignment changes it.

这篇关于如何“这个”在构造函数结束之前被引用/处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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