- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我曾经认为,从直觉上讲,Java 中的构造函数就是创建对象的东西,在其构造函数返回之前,没有任何东西可以触及该对象。然而,我一次又一次地被证明是错误的:
this
可以泄露未初始化的对象所有这些事实都违背了我认为构造函数是什么的直觉。
我再也不能自信地说出构造函数在 Java 中的实际作用,或者它的用途。如果我用所有最终字段制作一个简单的 DTO,那么我可以理解构造函数的用途是什么,因为这与 C 中的结构完全相同,只是它不能被修改.除此之外,我不知道在 Java 中可以可靠地使用哪些构造函数。它们只是一种约定/语法糖吗? (即,如果只有工厂为您初始化对象,您将只有 X x = new X()
,然后修改 x
中的每个字段,使它们没有默认值——考虑到上面的 3 个事实,这几乎等同于 Java 的实际情况)
我可以说出两个实际上由构造函数保证的属性:如果我执行 X x = new X()
,那么我知道 x
是 X
但不是 X
的子类,并且其最终字段已完全初始化。您可能会想说您知道 X
的构造函数已完成并且您有一个有效的对象,但如果您将 X
传递给另一个线程,这是不正确的 - the other thread may see the uninitialized version (即你刚才所说的与调用工厂的保证没有什么不同)。构造函数实际上保证了哪些其他属性?
最佳答案
All of these facts violate my intuition of what I thought a constructor is.
他们不应该。构造函数完全按照您的想法行事。
1: uninitialized objects can be leaked by sharing this
3: uninitialized objects can be leaked to another thread before they're fully constructed
this
的泄漏问题,在构造函数中启动线程,以及存储一个新构造的对象,多个线程在没有同步的情况下访问它,这些都是围绕非 final 的初始化重新排序的问题(和非 volatile )字段。但是初始化代码还是由构造函数完成的。构造对象的线程可以完整地看到对象。这是关于这些更改何时在其他线程中可见,这不是语言定义所保证的。
You might be tempted to say that you know that constructor of X finished and you have a valid object, but this is untrue if you pass X to another thread - the other thread may see the uninitialized version (i.e what you just said is no different than the guarantees of calling a factory).
这是正确的。同样正确的是,如果您有一个未同步的对象并且您在一个线程中改变它,其他线程可能会或可能不会看到该改变。这就是线程编程的本质。即使是构造函数也无法避免正确同步对象的需要。
2: uninitialized objects can be leaked by a subclass accessing it from the finalizer
本文档讨论的是终结器以及在对象被垃圾收集后不正确地访问对象的能力。通过破解子类和终结器,您可以生成一个未正确构造的对象,但这样做是一个主要的破解。对我来说,这不会以某种方式挑战构造函数的作用。相反,它展示了现代、成熟的 JVM 的复杂性。该文档还展示了如何编写代码来解决此问题。
What properties are guaranteed by constructors in Java?
根据定义,一个构造函数:
就您的 3 个问题而言,#1 和 #3 同样是关于何时非最终和非 volatile 字段的初始化被构造对象的线程以外的线程看到。不保证这种没有同步的可见性。
#2 问题展示了一种机制,如果在执行构造函数时抛出异常,您可以覆盖 finalize 方法来获取和不正确构造的对象。构造函数点 1-5 已发生。通过 hack,您可以绕过 6 的一部分。我想这是否会挑战构造函数的身份,这是旁观者的看法。
关于java - Java 中的构造函数保证了哪些属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16652966/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!