JDK-7087221 : Adding an operator to allow consistent equality tests when inheritance is used
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: linux
  • CPU: x86
  • Submitted: 2011-09-05
  • Updated: 2012-03-20
  • Resolved: 2011-10-31
Related Reports
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
"There is no way to extends an instantiable class and add a value component while preserving the equals contract" (Joshua Bloch's "Effective Java" 2nd edition, p. 38).

The reason is that sub classes' equals() method might consider fields the super class is not aware of. So we get:
Point p = new Point(1,2);
ColoredPoint cp = new ColoredPoint(1,2,Color.RED);  // ColoredPoint extends Point
p.equals(cp); // true
cp.equals(p); // false
(See there for more in-depth discussion)

Proposed solution:
add an at equality operator: @= (pronounces "at equality", so "a @= b" reads "a is at equality with b"). Semantically, "a @= b" is expanded to:
(a == b) || ( (a!=null && a.equals(b)) && (b!=null && (b.equals(a)) )

Optimizations:
1. The runtime or compiler can remove the null checks if they can prove that a or b cannot be null.
2. The runtime can remove one of the equals() invocations, if a and b are instances of the same class.
3. The runtime can remove one of the equals() invocations, if equals() is not overridden between the super class and the sub class.


JUSTIFICATION :
Adding the proposed operator @= to java would:
1. Make it possible to have consistent equality tests when inheritance is used
2. Eliminate a lot of boilerplate code for null tests (as equals() is a method)
3. Allow to "harness developer's laziness" (B. Goetz) for writing better, more robust code


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Point p = new Point(1,2);
ColoredPoint cp = new ColoredPoint(1,2,Color.RED);  // ColoredPoint extends Point
p @= cp; // false

But:
HashSet<Integer> hs = new HashSet<>();
TreeSet<Integer> ts = new TreeSet<>();
hs @= ts; // true
ACTUAL -
Compile error :-)

More seriously, programmers cannot add state fields to subclasses without compromising their ability to use equals() in a consistent way, which also hinders the ability to use the java collections:
Set<Point> pSet = new HashSet<>();
pSet.add( new Point(1,2) );
pSet.add( new ColoredPoint(1,2,Color.RED) );
pSet.size(); // ?? Implementation dependent.


CUSTOMER SUBMITTED WORKAROUND :
Some partial workarounds are possible (see pages 39-44 in Effective Java, 2nd edition).

Comments
EVALUATION Proposals for new features in the Java programming language are no longer being accepted or maintained in the bug database at http://bugs.sun.com/. This also applies to proposals for new features in the Java Virtual Machine (that is, in the abstract JVM, as opposed to a JVM implementation like HotSpot). All proposals for new features should be made through the "JDK Enhancement - Proposal & Roadmap Process" described at http://openjdk.java.net/jeps/1. Consequently, this specific request to change the Java programming language will not be considered further. The bug database continues to accept and maintain submissions about technical errors in the design and specification of the Java programming language and the Java Virtual Machine.
31-10-2011