Mill Hosper
Mill Hosper

Reputation: 49

The hashCode for String versus other class objects

class Employee {
  String name;

  Employee(String name) {
    this.name = name;
  }
  // hashCode method is not overridden
}

public class HashCodeConfusion {
  public static void main(String[] args) {
    Employee emp = new Employee("ABC");
    Employee emp1 = new Employee("ABC");

    if (emp == emp1) {
      System.out.println("Employee Same reference");
    } else {
      System.out.println("Employee Different reference");
    }
    if (emp.hashCode() == emp1.hashCode()) {
      System.out.println("Employee Same hash code");
    } else {
      System.out.println("Employee Different hash code");
    }

    // -----------------------------------

    String str = new String("ABC");
    String str1 = new String("ABC");

    if (str == str1) {
      System.out.println("String Same reference");
    } else {
      System.out.println("String Different reference");
    }
    if (str.hashCode() == str1.hashCode()) {
      System.out.println("String Same hash code");
    } else {
      System.out.println("String Different hash code");
    }
  }
}

Question/Confusion: The default hashCode for Object class seems to be taking into consideration the object reference and not just the contents, why else would the employee class object with the same name be coming out with a different hash code? If the default implementation of Object class had some hash algorithm based on contents alone, there would not be such a need to override the hashCode method as long as my equals paradigm agrees with the bitwise compatibility.

Anything to clear this confusion?

Upvotes: 0

Views: 119

Answers (1)

Peter Lawrey
Peter Lawrey

Reputation: 533432

The default hashCode() is not based on the reference, nor any address in the system. It is a randomly generated number stored in the header. It does this so the object can be moved without changing the hashCode() and the hashCode is reasonably random.

Note:

  • after a minor GC, the eden space is empty and the first object created is always at the same address. It doesn't have the same hashCode.
  • object are created on 8-byte boundaries by default, so the lower three bit can be all 000 which is not useful for a hashCode. If you use Compressed Oops, the lower bits might not be stored, but is still not very random.
  • Using Unsafe you can read and even overwrite the stored hashCode. On the OracleJVM/OpenJDK, the hashCode is stored 1 byte from the start of the object.
  • The bits used to store the hashCode is also used for baised locking. Once you obtain the builtin hashCode for an object, it will not use biased locking.
  • you can obtain the system hashCode of any object using System.identityHashCode(x) which is what IdentityMap uses.

Upvotes: 1

Related Questions