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

什么是“未完全构造的对象”?

唐焕
2023-03-14
问题内容

Goetz的Java Concurrency in
Practice
,第41页,提到了this在构造过程中如何逃避引用。“请勿执行此操作”示例

public class ThisEscape {
    public ThisEscape(EventSource source) {
        source.registerListener(
            new EventListener() {
                public void onEvent(Event e) {
                    doSomething(e);
                }
            });
    }
}

this是通过doSomething(e)引用封闭ThisEscape实例的事实进行的“转义”
。可以通过使用静态工厂方法(首先构造普通对象,然后注册侦听器)而不是公共构造函数(完成所有工作)来解决这种情况。这本书继续说:

从其构造函数中发布对象可能会发布不完整构造的对象。这是真实的 ,即使是公布在构造函数中的最后一条语句。
如果this参考在构造过程中逃逸,则认为该对象 构造不正确。

我不太明白。如果发布是构造函数中的最后一条语句,那么在此之前是否已完成所有构造工作?怎么会是this由当时不是有效?显然在那之后还有一些伏都教,但是呢?


问题答案:

就最终字段而言,就并发而言,构造函数的末尾是一个特殊的地方。从Java语言规范的17.5节开始:

对象的构造函数完成后,就认为该对象已完全初始化。保证只有在对象完全初始化之后才能看到对对象的引用的线程才能确保看到该对象的最终字段的正确初始化值。

最终字段的使用模型很简单。在该对象的构造函数中设置该对象的最终字段。不要在对象的构造函数完成之前,在另一个线程可以看到它的地方编写对正在构造的对象的引用。如果执行此操作,则当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本。它还将查看那些最终字段引用的任何对象或数组的版本,这些版本至少与最终字段一样。

换句话说,如果侦听器检查另一个线程中的对象,则最终可能会看到带有默认值的最终字段。如果在构造函数完成之后进行了侦听器注册,则不会发生这种情况。

就正在发生的事情而言,我怀疑构造函数的末尾存在隐式的内存屏障,以确保所有线程都“看到”新数据。如果没有应用该内存屏障,则可能会出现问题。



 类似资料:
  • 问题内容: 我曾经知道这是什么意思,但是我现在正在努力… 这基本上是在说什么吗? 问题答案: 它是立即调用的函数表达式,简称IIFE。它在创建后立即执行。 它与任何事件(例如)的事件处理程序无关。 考虑第一对括号中的部分:....它是一个正则函数表达式。然后查看最后一对,通常将其添加到表达式中以调用函数;在这种情况下,我们的先前表达。 当试图避免污染全局名称空间时,通常使用此模式,因为IIFE内部

  • 本文向大家介绍请解释Java中的概念,什么是构造函数?什么是构造函数重载?什么是复制构造函数?相关面试题,主要包含被问及请解释Java中的概念,什么是构造函数?什么是构造函数重载?什么是复制构造函数?时的应答技巧和注意事项,需要的朋友参考一下 考察点:JAVA构造函数 当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一

  • 问题内容: 我刚刚在NodeJS环境中看到关键字的奇怪行为。我正在用代码列出它们。我已经使用,用一个文件运行了这些代码。 如下用一行代码进行测试时,无论是否使用该语句,这都指向一个空对象。 但是,当我在自执行函数中运行语句时, 它正在打印一个非常大的对象。在我看来,环境创建的全局执行上下文对象。 并且在执行带有语句的上述功能时,预期它正在打印 但是,在使用浏览器时(我仅使用进行了测试),前三个示例

  • 问题内容: 所以我正在学习Java。我有一个月的时间,我刚刚了解了构造函数。但是我看不到创建一个的全部目的。为什么我什么时候要使用?我知道它没有主方法,您可以从主类中调用构造函数。任何人都可以启发我这个话题,这对我有很大帮助。 问题答案: 构造函数是用来初始化/设置类实例的对象。 如果您有一个对象需要一些处理才能使用(例如,初始化成员),则应在构造函数中执行此操作。 理想情况下,您永远不应拥有“部

  • 上这个简单的课... JLS的第8.8.9节指出,“如果一个类不包含构造函数声明,那么默认构造函数将被隐式声明。”它还说,只要我们不在类中,那么“默认构造函数只是调用没有参数的超类构造函数。” 因此,因为类扩展了,我们被迫通过调用的构造函数,作为隐式创建的默认构造函数的一部分。 同样地... 即使我们显式地为Gen声明构造函数,JLS的第8.8.7节规定“如果构造函数体不是以显式构造函数调用开始,

  • 内部构造函数的准确定义是什么?在Julia-V0.6+中,“任何可以使用签名(注意部分)调用的构造函数都是内部构造函数”是正确的吗? 正如下面的注释中所讨论的,仅限于外部的构造函数实际上是吗? 使用检查方法是否是内部/外部构造函数是否正确? Julia自动定义的默认构造函数与用户显式定义的相应构造函数有什么不同? 顺便说一句,我知道如何使用以及何时使用内部构造函数。我知道什么是内部构造函数,直到只