我不确定作者写单例静态工厂方法可以保证不存在两个相等的实例是什么意思。好吧,实际上我确实有点理解这一点,但是当他演示等于方法与文字比较运算符时,我对以下文本感到困惑:">a.equals(b) 当且仅当 a==b。
我知道equals()
方法实际上比较对象的内容,而文字==
进行比较以查看它们是否是内存中的同一对象。这令人困惑,因为他接着说客户端可以使用==
而不是.equals(object)
方法。怎么会这样?如果保证客户端只有一个对象,为什么还要使用==
比较器?
有人可以给我写一个简短的编码示例来更具体地解释这一点吗?
作者全文如下:
静态工厂方法从 重复调用允许类保持对 任何时候都存在哪些实例。这样做的类被称为 实例控制。写作有几个原因 实例控制的类。实例控制允许类 保证它是单例(项目 3)或不可实例化(项目 4)。 此外,它允许不可变类(第 15 项)做出保证 不存在两个相等的实例:a.equals(b) 当且仅当 a==b。如果 类做出此保证,然后其客户端可以使用 == 运算符 而不是 equals(Object) 方法,这可能会导致改进 性能。枚举类型(第 30 项)提供此保证。
在你引用的顶部的特定片段中,他谈到了在不可变类的实例中为每个可能的值集强制实施一个实例:
此外,它允许不可变类(第 15 项)做出保证 不存在两个相等的实例:a.equals(b) 当且仅当 a==b
也就是说,您可能希望静态工厂保证如果a
和b
表示相同的值,则它们是内存中的同一实例(即不能存在重复项)。如果这是真的,那么==
的工作方式与equals(Object)
相同,这意味着您可以自由使用您认为可能有助于性能的==
。
正如乔恩在评论中所说,静态工厂不仅限于单例。
我想你几乎已经明白了。静态方法做出以下承诺,"如果您请求一个新对象将 .equals() 与现有对象进行比较,我将返回现有对象"。鉴于这种保证,您知道a.equals(b)
意味着a == b
,并且您知道a == b
意味着a.equals(b)
。因此,如果要查看a
和b
是否相等,可以使用==
运算符而不是.equals
方法。这很有用,因为==
非常快,而且根据对象类型,.equals
可能会很慢。
这是一个具体的例子。假设我们有一个 person 类。一个人是由他们的名字和姓氏定义的(假装世界上没有两个人同名)。我的类可能看起来像这样(没有尝试编译,所以不能保证正确性):
class Person {
private final String fname;
private final String lname;
// Private constructor - must use the static method
private Person(String first, String last) {fname = first; lname = last;}
// Note that this is slow - the time it takes is proportional to the length of the
// two names
public boolean equals(Object o) {
// Should check types here, etc.
Person other = (Person) o;
if (!person.fname.equals(other.fname)) {return false;}
if (!person.lname.equals(other.lname)) {return false;}
return true;
}
// Registry of all existing people
private static Map<String, Person> registry = new TreeMap<String, Person>();
public static getPerson(String fname, String lname) {
String fullName = fname + "-" + lname;
// If we already have this person, return that object, don't construct a new one.
// This ensures that p1.equals(p2) means that p1 == p2
if (registry.containsKey(fullName)) {return registry.get(fullName);}
Person p = new Person(fname, lname);
registry.put(fullName, p);
return p;
}
}
然后你可以像这样使用它:
public boolean isSamePerson(Person p1, Person p2) {
// Guaranteed to have the same result as "return p1.equals(p2)" but will be faster
return p1 == p2;
}
如果您可以保证(也许使用蝇量级模式)相等的对象将具有相同的引用,那么调用者可以使用==
(并获得性能优势);例如,考虑一个enum
类型...您可以使用==
来确定任何两个enum
实例是否相同。