Java 中的相等性能( instanceOf 与 isAssignableFrom )

sma*_*007 5 java oop jvm scala equality

这个问题特别是关于各种实现替代方案的性能和在某种程度上的简洁性。

这篇关于实现平等权利的文章让我精神焕发。我的问题特别对应于canEqual(以确保等价关系)。

而不是重载 canEquals 方法以在层次结构中的每个类中使用 instanceOf (paramenter 的实例是编译时类)。为什么不只在顶级类中使用 isAssignableFrom(动态解析)。使代码更加简洁,您不必重载第三种方法。

虽然,这种替代方法有效。是否有任何我需要注意的性能注意事项?

enum Color {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET;
}
class Point {

    int x;
    int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }


    @Override public boolean equals(Object other) {
        boolean result = false;
        if (other instanceof Point) {
            Point that = (Point) other;
            //Option 1
            //result = (that.canEqual(this) && this.getX() == that.getX() && this.getY() == that.getY());
            //Option 2
            //result = (that.getClass().isAssignableFrom(this.getClass()) && this.getX() == that.getX() && this.getY() == that.getY());
            //Option 3
            //result = (getClass() == that.getClass() && this.getX() == that.getX() && this.getY() == that.getY());
        }
        return result;
    }

    @Override public int hashCode() {
        return (41 * (41 + x) + y);
    }

    public boolean canEqual(Object other) {  return (other instanceof Point);   }
}

public class ColoredPoint extends Point{
      Color color;

        public ColoredPoint(int x, int y, Color color) {
            super(x, y);
            this.color = color;
        }

        @Override public boolean equals(Object other) {
            boolean result = false;
            if (other instanceof ColoredPoint) {
                ColoredPoint that = (ColoredPoint) other;
                result = (this.color.equals(that.color) && super.equals(that));
            }
            return result;
        }

        @Override public int hashCode() {
            return (41 * super.hashCode() + color.hashCode());
        }

        @Override public boolean canEqual(Object other) {    return (other instanceof ColoredPoint);   }

    public static void main(String[] args) {
        Object p = new Point(1, 2);
        Object cp = new ColoredPoint(1, 2, Color.INDIGO);

        Point pAnon = new Point(1, 1) {
            @Override public int getY() {
                return 2;
            }
        };

        Set<Point> coll = new java.util.HashSet<Point>();
        coll.add((Point)p);

        System.out.println(coll.contains(p)); // prints true
        System.out.println(coll.contains(cp)); // prints false
        System.out.println(coll.contains(pAnon)); // prints true
    }
}
Run Code Online (Sandbox Code Playgroud)

wax*_*ing 5

更新:实际上,您的方法在技术上并不像我最初想的那样有效,因为它破坏了equals不覆盖的子类的对称契约equals

Point p = new Point(1, 2);
Point pAnon = new Point(1, 1) {
    @Override public int getY() {
        return 2;
    }
};

System.out.println(p.equals(pAnon)); // prints false
System.out.println(pAnon.equals(p)); // prints true
Run Code Online (Sandbox Code Playgroud)

其原因是,p.getClass().isAssignableFrom(pAnon.getClass())true,而逆,pAnon.getClass().isAssignableFrom(p.getClass())false

如果您对此不信服,请尝试实际运行您的代码并将其与文章中的版本进行比较:您会注意到它打印true, false, false,而不是true, false, true像文章中的示例那样。


jta*_*orn 3

除非您想允许比较不同类型的类,否则最简单、最安全、最简洁且可能最有效的实现是:

(getClass() == that.getClass())
Run Code Online (Sandbox Code Playgroud)