为什么要在布尔和类似的不可变类上使用公共构造函数?

Rob*_*ker 5 java constructor immutability

(出于这个问题的目的,让我们假设一个人故意不使用自动(非)拳击,因为一个人正在编写Java 1.5之前的代码,或者因为一个人认为自动装箱使得创建NullPointerExceptions 太容易了.)

就拿Boolean,例如.Boolean(boolean)构造函数的文档说:

注意:使用此构造函数很少是合适的.除非需要 实例,否则静态工厂valueOf(boolean)通常是更好的选择.它可能会产生明显更好的空间和时间性能.

我的问题是,为什么你永远要摆在首位获得一个新的实例?如果像这样的构造函数是私有的,那么事情似乎会更简单.例如,如果它们是,你可以写这个没有危险(即使myBooleannull):

if (myBoolean == Boolean.TRUE)
Run Code Online (Sandbox Code Playgroud)

它是安全的,因为所有的真实Booleans都是引用Boolean.TRUE,所有的错误Booleans都是引用Boolean.FALSE.但是因为构造函数是公共的,所以有人可能已经使用过它们,这意味着你必须编写它:

if (Boolean.TRUE.equals(myBoolean))
Run Code Online (Sandbox Code Playgroud)

但真正变坏的地方在于你想要检查两个Booleans是否平等.像这样的东西:

if (myBooleanA == myBooleanB)
Run Code Online (Sandbox Code Playgroud)

......变成这个:

if (
    myBooleanA == myBooleanB ||
    (myBooleanA != null && myBooleanA.equals(myBooleanB))
)
Run Code Online (Sandbox Code Playgroud)

更新:随着Java 7的发布,java.util.Objects使这个更简单的构造成为可能:

if (Objects.equals(myBooleanA, myBooleanB))
Run Code Online (Sandbox Code Playgroud)

我想不出有任何理由让这些对象具有单独的实例,这比不必做上面的废话更有说服力.怎么说你?

Bal*_*usC 5

缓存的值永远不会被垃圾收集,因此每当您想要将它们用作软/弱引用时,请使用构造函数,以便无论何时需要时都可以对其进行垃圾收集.这同样适用于Long#valueOf(),Integer#valueOf()并且可以在可缓存范围内使用值.

这样做在Eclipse中的参考搜索得知我在每个java.lang.Thread使用new Boolean()作为软参考基础的缓存,它甚至明确(评论中的isCCLOverridden()方法):

/*
 * Note: only new Boolean instances (i.e., not Boolean.TRUE or
 * Boolean.FALSE) must be used as cache values, otherwise cache
 * entry will pin associated class.
 */
Run Code Online (Sandbox Code Playgroud)