繁体   English   中英

Joshua Bloch 项目 #1 Static 工厂方法代替构造函数 - Object 创建

[英]Joshua Bloch Item #1 Static Factory Methods Instead of Constructors - Object creation

问题来源

我想知道 Joshua Blochs“Effective Java”第 3 版第 1 项中描述的 Static 工厂方法的以下优点:

static 工厂方法的第二个优点是,与构造函数不同,它们不需要在每次调用时都创建一个新的 object。 这允许不可变类(条目 15)使用预构造的实例,或者在构造实例时缓存实例,并重复分配它们以避免创建不必要的重复对象。 Boolean.valueOf(boolean) 方法说明了这种技术:它从不创建 object。

请参阅此处的摘录。

问题

引起我注意的是关于valueOf(boolean)没有创建 object 的最后一行。根据这本书

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

Javadoc

public static Boolean valueOf(boolean b)

返回表示指定 boolean 值的 Boolean 实例。 如果指定的 boolean 值为真,则此方法返回 Boolean.TRUE; 如果为假,则此方法返回 Boolean.FALSE。 如果不需要新的 Boolean 实例,通常应优先使用此方法而不是构造函数 Boolean(boolean),因为此方法可能会产生明显更好的空间和时间性能。

因此,根据我的理解和 Javadoc(“返回 Boolean 实例...”),static 方法确实返回 Boolean,因此返回 object - 因为它实际上是返回类型。 在以下情况下:

public class MyClass {
    public static void main(String args[]) {
        Boolean booleanWrapped = Boolean.valueOf(true);
        System.out.println(booleanWrapped);
    }
}

booleanWrapped是我的 object 我可以像在prinln()语句中一样使用 eg。

那么如果约书亚说我在这里错过了什么

Boolean.valueOf(boolean) [...]永远不会创建 object

我知道一个带有现有答案的类似问题,但它似乎没有完全回答我的问题,因为在我上面的示例中没有“预先存在的”实例。?!

您的 booleanWrapped 变量不引用新创建的 object。它引用 static Boolean.TRUE第一次创建 Boolean class 负载。 Boolean.valueOf(true)的所有调用都简单地重复使用单个 object。

自 Java 9 起,Boolean 已弃用构造函数。 但这仍然表明了差异。

所以Boolean b1 = new Boolean(true). 创建一个新实例并将其存储在b1中。

Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean(true);
System.out.println(System.identityHashCode(b1));
System.out.println(System.identityHashCode(b2));

两个不同的身份哈希码表示不同的对象

804564176
1421795058

现在使用现有的 static 实例。

Boolean b1 = Boolean.TRUE;
Boolean b2 = Boolean.TRUE;
System.out.println(System.identityHashCode(b1));
System.out.println(System.identityHashCode(b2));

共享相同的 object - 相同的哈希码。

804564176
804564176

在 Boolean class 中,您有以下内容:

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

所以它们是在加载 class 时创建的。

valueOf方法永远不会创建一个新的 object(没有new表达式,也没有其他可以传递调用构造函数的方法调用)。 该方法仅返回 2 static 字段之一( Boolean.TRUEBoolean.FALSE )。 这些字段已经存在并且它们引用的对象已经创建(在方法valueOf之外和之前)。

显然,必须在某处创建对象; 但它们不是在方法valueOf中创建的。

而“返回一个对象”。=“创建一个对象”。

public static Object demo() {
  final Object obj = new Object(); // `new` creates the object
  return obj; // `return` returns the object, it does not create a new one
}

Boolean.TRUEBoolean.FALSE都是预先存在的static成员,由 Boolean class 定义。

在理解 static 工厂方法相对于传统构造函数的优势时,一个不可忽视的重要概念是为什么 Josh Bloch 指定可以缓存或预构造不可变类。 重点不在于在第一次调用static工厂方法时是否构造了一个object,而是在多次使用时如何节省资源。 节省的全部是返回一个预先存在的不可变实例,而不是构建一个新实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM