zoukankan      html  css  js  c++  java
  • Effective Java 08 Obey the general contract when overriding equals

    When it's the case that each instance of the class is equal to only itself.

    1. Each instance of the class is inherently unique.

    2. You don't care whether the class provides a "logical equality" test.

    3. If a superclass has already overridden equals, and the superclass behavior is appropriate for this class.

    4. The class is private or package-private, and you are certain that its equals method will never be invoked.

       

    Arguably, the equals method should be overridden under these circumstances, in case it is accidentally invoked:

    @Override public boolean equals(Object o) {

    throw new AssertionError();

    // Method is never called

    }

       

    When a class has a notion of logical equality that differs from mere object identity, and a superclass has not already overridden equals to implement the desired behavior.

       

    The equals method implements an equivalence relation. It is:

    • Reflexive: For any non-null reference value x, x.equals(x)must return true.

    • Symmetric: For any non-null reference values x and y, x.equals(y)must return true if and only if y.equals(x) returns true.

       

    @Override public boolean equals(Object o) {

    return o instanceof CaseInsensitiveString &&

    ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);

    }

       

    • Transitive: For any non-null reference values x, y, z, if x.equals(y)returns

    True and y.equals(z)returns true, then x.equals(z)must return true.

       

    // Adds a value component without violating the equals contract

    public class ColorPoint {

    private final Point point;

    private final Color color;

    public ColorPoint(int x, int y, Color color) {

    if (color == null)

    throw new NullPointerException();

    point = new Point(x, y);

    this.color = color;

    }

    /**

    * Returns the point-view of this color point.

    */

    public Point asPoint(){

    return point;

    }

    @Override public boolean equals(Object o) {

    if (!(o instanceof ColorPoint))

    return false;

    ColorPoint cp = (ColorPoint) o;

    return cp.point.equals(point) && cp.color.equals(color);

    }

    ... // Remainder omitted

    }

       

    NOTE

    Never use Timpstamp and java.util.Date class together in same collection since the Timpstamp does violate symmetry and can cause erratic behavior.

    • Consistent: For any non-null reference values x and y, multiple invocations Of x.equals(y)consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.

       

    mutable objects can be equal to different objects at different times while immutable objects can't.

    Java.net.URL's equals method relies on comparison of the IP addresses of the hosts associated with the URLs. Translating a host name to an IP address can require network access, and it isn't guaranteed to yield the same results over time.

    • For any non-null reference value x, x.equals(null)must return false.

       

    Recipe for a high-quality equals method

    1. Use the ==operator to check if the argument is a reference to this object

    2. Use the instanceof operator to check if the argument has the correct type

    3. Cast the argument to the correct type

    4. For each "significant" field in the class, check if that field of the argument

    matches the corresponding field of this object

    NOTE

    If the type in step 2 is an interface, you must access the argument's fields via interface methods; if the type is a class, you may be able to access the fields directly, depending on their accessibility.

       

    (field == null ? o.field == null : field.equals(o.field))

       

    Primitive type: use == operator (float & double use Float.compare & Double.compare respectively to prevent -0.0).

       

    Array fields: apply above guideline to each element ( If every element in an array field is significant, you can use one of the Arrays.equals)

       

    5. When you are finished writing your equals method, ask yourself three

    questions: Is it symmetric? Is it transitive? Is it consistent?

       

    NOTE:

    1. Always override hashCode when you override equals

    2. Consistent use of the @Override annotation, as illustrated throughout this item, will prevent you from making this mistake (Item 36). This equals method won't compile and the error message will tell you exactly what is wrong:

    @Override

    public boolean equals(MyClass o) {

    ...

    }

    作者:小郝
    出处:http://www.cnblogs.com/haokaibo/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅶ(延伸:堆排序的实现)
    《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅵ
    《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅴ
    Uva227.Puzzle
    UVa1587.Digit Counting
    《Two Days DIV + CSS》读书笔记——CSS选择器
    《Two Days DIV + CSS》读书笔记——CSS控制页面方式
    《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅳ
    《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅲ
    校赛总结
  • 原文地址:https://www.cnblogs.com/haokaibo/p/obey-the-general-contract-when-overriding-equals.html
Copyright © 2011-2022 走看看