SDA SE Wiki

Software Engineering for Smart Data Analytics & Smart Data Analytics for Software Engineering

User Tools

Site Tools


Bug JT_BAD_031

Inspired by

Original Description

“This class overrides equals(Object), but does not override hashCode(). Therefore, the class may violate the invariant that equal objects must have equal hashcodes.” – 2013-10-13

Detailed Description

While overriding the equals(Object) method, its a necessity to override the hashCode() method as well. As according to the Java contract equals and hashCode are bounded together with a joint contract specifying that if two objects are equal using the equals(Object) method then they mush have identical hashcode value.


This has to be followed as objects which are considered equal, should be able to used interchangeably in Collections such as HashMap. The below code shows an example where if you, don't override the hashcode method, the objects returning true in equals(Obejct) cannot retrieve values from hashMap interchangeably. The corrected code overrides hashCode and return the same value for both the objects, thus making it possible to retrieve information from Collections with object returning true for equals method.

Sample Problem Scenario

import java.util.HashMap;
 
public class HE_EQUALS_NO_HASHCODE {
	public static void main(String[] args) {
		Moof moof1 = new Moof(8);
		Moof moof2 = new Moof(8);
		HashMap<Moof, String> hashMap = new HashMap<Moof, String>();
 
		//Comparing moof1 and moof2 via overridden equals method
		System.out.println(moof1.equals(moof2)); //Output true
 
		//Entering a value in the map using moof1 object
		hashMap.put(moof1, "Should Return with Moof2");
		//Retrieving the value from the map using moof2 object
		System.out.println(hashMap.get(moof2)); // Output : null
	}
 
}
 
class Moof{
	private int val;
	public Moof(int val){
		this.val = val;
	}
	public int getVal() {
		return val;
	}
	public void setVal(int val) {
		this.val = val;
	}
	/*
	 * @see java.lang.Object#equals(java.lang.Object)
	 * @parameters Object
	 * @return boolean
	 * @description To make 2 objects equal whose instance variable val are equal.
	 */
	public boolean equals(Object obj){
		if(obj instanceof Moof && this.val == ((Moof)obj).val){
			return true;
		}
		return false;
	}	
}

Sample Fix

import java.util.HashMap;
 
public class HE_EQUALS_HASHCODE {
	public static void main(String[] args) {
		MoofWithHashCode moof1 = new MoofWithHashCode(8);
		MoofWithHashCode moof2 = new MoofWithHashCode(8);
		HashMap<MoofWithHashCode, String> hashMap = new HashMap<MoofWithHashCode, String>();
 
		// Comparing moof1 and moof2 via overridden equals method
		System.out.println(moof1.equals(moof2)); // Output true
 
		// Entering a value in the map using moof1 object
		hashMap.put(moof1, "Should Return with Moof2");
		// Retrieving the value from the map using moof2 object
		System.out.println(hashMap.get(moof2)); // Output : Should Return with Moof2
	}
 
}
 
class MoofWithHashCode {
	private int val;
 
	public MoofWithHashCode(int val) {
		this.val = val;
	}
 
	public int getVal() {
		return val;
	}
 
	public void setVal(int val) {
		this.val = val;
	}
 
	/*
	 * @see java.lang.Object#equals(java.lang.Object)
	 * @parameters Object
	 * @return boolean
	 * @description To make 2 objects equal whose instance variable val are
	 * equal.
	 */
	public boolean equals(Object obj) {
		if (obj instanceof MoofWithHashCode && this.val == ((MoofWithHashCode) obj).val) {
			return true;
		}
		return false;
	}
	/*
	 * @see hashCode()
	 * @parameters none
	 * @return int
	 * @description returns hashcode for the Integer val.
	 * equal.
	 */
	public int hashCode(){
		return new Integer(this.val).hashCode();
	}
}
teaching/labs/mdse/2013/bug_descriptions/jt-bug-he_equals_no_hashcode.txt · Last modified: 2019/06/19 11:35 by Günter Kniesel

SEWiki, © 2023