Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

Wiki MarkupClasses that override the {{Object.equals()}} method must also override the {{Object.hashCode()}} method. The {{java.lang.Object}} class requires that any two objects that compare equal using the {{equals()}} method must produce the same integer result when the {{hashCode()}} method is invoked on the objects \ [[API 2006|AA. References#API 06]\].

The equals() method is used to determine logical equivalence between object instances. Consequently, the hashCode() method must return the same value for all equivalent objects. Failure to follow this contract is a common source of defects.

...

The cause of this erroneous behavior is that the CreditCard class overrides the equals() method but fails to override the hashCode() method. Consequently, the default hashCode() method returns a different value for each object, even though the objects are logically equivalent; these differing values lead to examination of different buckets in the hash table, which prevents the get() method from finding the intended value.
Note that by specifying the credit card number in main(), these code examples violate rule MSC03-J. Never hard code sensitive information for the sake of brevity.

Compliant Solution

Wiki MarkupThis compliant solution overrides the {{hashCode()}} method so that it generates the same value for any two instances that are considered to be equal by the {{equals()}} method. Bloch discusses the recipe to generate such a hash function in detail \ [[Bloch 2008|AA. References#Bloch 08]\].

Code Block
bgColor#ccccff
public final class CreditCard {
  private final int number;
  
  public CreditCard(int number) {
    this.number = number;
  }

  public boolean equals(Object o) {
    if (o == this) {
      return true;
    } 
    if (!(o instanceof CreditCard)) {
      return false;
    }
    CreditCard cc = (CreditCard)o;
    return cc.number == number; 
  }

  public int hashCode() {
    int result = 17;
    result = 31 * result + number;
    return result;
  }

  public static void main(String[] args) {
    Map<CreditCard, String> m = new HashMap<CreditCard, String>();
    m.put(new CreditCard(100), "4111111111111111");
    System.out.println(m.get(new CreditCard(100)));
  }
}

...

MITRE CWE

CWE-581. Object model violation: Just one of equals and hashcode Defined

Bibliography

...

[[API 2006AA. References#API 06]]

[Class Objecthttp://java.sun.com/javase/6/docs/api/java/lang/ Object.html]

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="c21f1d9c-8b89-4a25-a37b-4ffee20b3dd9"><ac:plain-text-body><![CDATA[

[ [Bloch 2008AA. References#Bloch 08] ]

Item 9. Always override hashCode when you override equals]]></ac:plain-text-body></ac:structured-macro>

...

      05. Methods (MET)