Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4355763

DefaultCaret.equals() violates the symmetric rule for equals()



    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Won't Fix
    • Affects Version/s: 1.3.0
    • Fix Version/s: None
    • Component/s: client-libs


      Name: sl110371 Date: 07/24/2000

      java version "1.3.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
      Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

      According to the documentation for java.lang.Object.equals(), the equals method
      is supposed to be symmetric. Which means x.equals(y) should return true if and
      only if y.equals(x) returns true. In javax.swing.text.DefaultCaret, this is
      violated. Here's the code to reproduce.

      Rectangle rect = new Rectangle(1, 2, 3, 4);
      javax.swing.text.DefaultCaret dc = new javax.swing.text.DefaultCaret();
      dc.setSize(3, 4);
      dc.setLocation(1, 2);
      System.out.println("rect.equals(dc)=" + rect.equals(dc));
      System.out.println("dc.equals(rect)=" + dc.equals(rect));

      Run it and you'll get:

      This is obviously contradictory to the java.lang.Object documentation. This
      occurs because Rectangle compares x, y, width & height. DefaultCaret does a
      reference equality. And since DefaultCaret extends Rectangle, voila!

      The bad part is whether or not this behavior is correct. If you override
      equals() in a class, and then you subclass it and add additional data members
      and override equals(), you get what I just explained above. If Rectangle did a
      obj.getClass().equals(Rectangle.class) then the behavior would be correct,
      however all subclasses of Rectangle would lose that equals functionality.

      So generally, if B is a subclass of A, and A defines equals() to check for data
      equality, and B does the same but also checks its additional data, then using
      only the instanceof operator violates the rule for symmetry in equals(). The
      worst part is if you have interface A and interface B, which extends A (data
      similar to the class example). And you have a corresponding implementation for
      each that overrides equals(). If you want to preserve checking equality at the
      interface level only, then you have to analyze the full class hierarchy
      structure for every passed in object to make sure it doesn't implement a
      subinterface of you that would violate the symmetry rule.

      I think I've made my point, and I'd love some feedback on this because I really
      don't have a good answer to this problem yet.
      (Review ID: 107469)


          Issue Links



              svioletsunw Scott Violet (Inactive)
              duke J. Duke (Inactive)
              0 Vote for this issue
              0 Start watching this issue