关于有效Java文本的困惑

时间:2013-12-30 20:21:57

标签: java methods static factory

我不确定作者在写道单独的静态工厂方法可以保证不存在两个相等的实例时的含义。实际上我有点理解这一点,但是当他演示equals方法与文字比较运算符时,我对以下文本感到困惑:“a.equals(b)当且仅当a == b。”< / em>的

我理解equals()方法实际上比较了对象的内容,而文字==进行比较,看它们是否是内存中的同一个对象。这很令人困惑,因为他继续说客户端可以使用==而不是.equals(object)方法。怎么会这样?如果客户只保证一个对象,为什么客户端会使用==比较器?

有人可以给我写一个简短的编码示例来更具体地解释这个吗?

作者的文字如下:

  

静态工厂方法从中返回相同对象的能力   重复调用允许类保持严格控制   什么实例随时存在。据说这样做的类   实例的控制。写作有几个原因   实例控制的类。实例控件允许类   保证它是单例(第3项)或不可实例化(第4项)。   此外,它允许不可变类(第15项)作出保证   没有两个相等的实例存在:a.equals(b)当且仅当a == b。如果   一个类做出这个保证,然后它的客户端可以使用==运算符   而不是equals(Object)方法,这可能会导致改进   性能。枚举类型(第30项)提供此保证。

3 个答案:

答案 0 :(得分:3)

在顶部引用的特定代码段中,他正在讨论在不可变类的实例中为每个可能的值集强制执行一个实例:

  

此外,它允许不可变类(第15项)进行保证   没有两个相等的实例存在:a.equals(b)当且仅当a == b

也就是说,您可能希望静态工厂保证如果ab表示相同的值,则它们在内存中是相同的实例(即重复项不可存在)。如果是这样,那么==的工作方式与equals(Object)的工作方式相同,这意味着您可以自由地使用==,而您认为它可能对性能有所帮助。

正如乔恩在评论中所说,静态工厂不仅限于单身人士。

答案 1 :(得分:2)

我想你差不多了。静态方法做出以下承诺,“如果你请求一个将.equals()与现有对象进行比较的新对象,我将返回现有对象”。鉴于该保证,您知道a.equals(b)表示a == b,并且您知道a == b表示a.equals(b)。因此,如果您想查看ab是否相等,则可以使用==运算符代替.equals方法。这很有用,因为==非常快,并且根据对象类型,.equals可能会很慢。

这是一个具体的例子。假设我们有一个人类。一个人用他们的名字和姓氏来定义(假装世界上没有两个同名的人)。我的类可能看起来像这样(没有尝试编译,因此无法保证正确性):

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;
}

答案 2 :(得分:1)

如果您可以保证(可能使用Flyweight模式)相同的对象具有相同的指示对象,则调用者可以使用==(并获得性能优势);例如,考虑enum类型...您可以使用==来确定是否有任何两个enum实例相同。