Bug 167304

Summary: [hashcode/equals] Suggestion for shorter Equals
Product: [Eclipse Project] JDT Reporter: William Voorsluys <williamvoor>
Component: UIAssignee: JDT-UI-Inbox <jdt-ui-inbox>
Status: NEW --- QA Contact:
Severity: enhancement    
Priority: P3    
Version: 3.2.1   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:

Description William Voorsluys CLA 2006-12-08 18:13:08 EST
I've been using the "Generate equals and hashCode" feature of Eclipse. I consider it very usefull except for the fact that it generates a too long equals method.
On some of my code, I've changed some comparisons to get shorter equals  methods with same functionality. On a class with 3 Object fields, it is possible to generate a 20 lines shorter equals, using comparison expressions. Like this:

public class AnyClass {

    private Object field1;
    private Object field2;
    private Object field3;

    public boolean equals( Object obj ) {

        if ( this == obj )
            return true;
        if ( obj == null )
            return false;
        if ( getClass() != obj.getClass() )
            return false;
        final AnyClass other = (AnyClass) obj;
        if ( !(this.field1 == null ? other.field1 == null : this.field1.equals( other.field1 )) )
            return false;
        if ( !(this.field2 == null ? other.field2 == null : this.field2.equals( other.field2 )) )
            return false;
        if ( !(this.field3 == null ? other.field3 == null : this.field3.equals( other.field3 )) )
            return false;
        return true;
    }
}

In constrast to the equals generated by Eclipse:


    public boolean equals( Object obj ) {

        if ( this == obj )
            return true;
        if ( obj == null )
            return false;
        if ( getClass() != obj.getClass() )
            return false;
        final AnyClass other = (AnyClass) obj;
        if ( this.field1 == null ) {
            if ( other.field1 != null )
                return false;
        } else if ( !this.field1.equals( other.field1 ) )
            return false;
        if ( this.field2 == null ) {
            if ( other.field2 != null )
                return false;
        } else if ( !this.field2.equals( other.field2 ) )
            return false;
        if ( this.field3 == null ) {
            if ( other.field3 != null )
                return false;
        } else if ( !this.field3.equals( other.field3 ) )
            return false;
        return true;
    }

Certainly, some programmers do not like those expressions, as it may make the code harder to read. So, even this enhancement could be a "Clean Up" or an option when generating Equals, not necessarily the default implementation.
Comment 1 Olivier Thomann CLA 2006-12-08 23:16:42 EST
Moving to JDT/UI
Comment 2 Alex Blewitt CLA 2006-12-10 04:54:03 EST
You can make it even shorter than that using a collection of 'and' combinators:

AnyClass other = (obj instanceof AnyClass ? (AnyClass)obj : null );
return
  this == obj ||
  (
    obj != null &&
    getClass() == obj.getClass() &&
    !(this.field1 == null ? other.field1 == null : this.field1(equals(other.field1)) &&
    !(this.field2 == null ? other.field2 == null : this.field2(equals(other.field2)) &&
  );

i'm not sure how either the formatter would handle this, or the average programmer reading it, either. It would also be interesting to see (from a compiled approach) which one is better, or whether it makes any significant difference..

Alex.