CuriousMind
CuriousMind

Reputation: 8903

Default hashCode() implementation for Java Objects

I was trying to understand the hashCode() for Java's Object and saw the following code for Java Object's hashCode() method:

package java.lang;
public class Object {

 // Some more code

 public native int hashCode();

 // Some other code

}

Now, we know that if we create a class it implicitly extends the Object class, and to do this I wrote a sample example:

package com.example.entity;
public class FirstClass {
    private int id;
    private String name;
    // getters and setters
}

So, this class viz: FirstClass would be extending the Object class implicitly.

Main class:

package com.example.app.main;
import com.example.entity.FirstClass;
    public class MainApp {
        public static void main(String[] args) {
             FirstClass fs = new FirstClass();
             fs.setId(1);
             fs.setName("TEST");
             System.out.println("The hasCode for object fs is " + fs.hashCode());
         }
 }

As FirstClass is extending Object class implicitly, hence it would have Object classes' hashCode() method.

I invoked the hashCode() on FirstClass object , and as I haven't overridden the hashCode(), by theory it should invoke Object class's hashCode().

My doubt is:

As Object class don't have any implementation, how is it able to calculate the hash-code for any object?

In my case, when I run the program the hash-code which it returned was 366712642.

Can anyone help me understand this?

Upvotes: 12

Views: 12248

Answers (3)

GhostCat
GhostCat

Reputation: 140407

You are getting things wrong:

public native int hashCode();

doesn't mean there is no implementation. It just means that the method is implemented in the native aka C/C++ parts of the JVM. This means you can't find Java source code for that method. But there is still some code somewhere within the JVM that gets invoked whenever you call hashCode() on some Object.

And as the other answer explains: that "default" implementation used the "memory" address of the underlying object. Thing is: using java means, there is no knowledge of "memory addresses". Keep in mind: the JVM is written in C/C++ - and the real memory management happens in these native parts of the JVM.

In other words: you can't write Java code that tells you about the "native memory address" of an object.

But as the other answer by Eugene makes clear: the hash being about "memory location" is a thing of the past.

Upvotes: 7

Eugene
Eugene

Reputation: 120848

Even though there are some answers here stating that the default implementation is "memory" based, this is plain wrong. This is not the case for a lot of years now.

Under java-8, you can do :

java -XX:+PrintFlagsFinal | grep hashCode

To get the exact algorithm that is used (5 being default).

  0 == Lehmer random number generator, 
  1 == "somehow" based on memory address
  2 ==  always 1
  3 ==  increment counter 
  4 == memory based again ("somehow")
  5 == read below

By default (5), it is using Marsaglia XOR-Shift algorithm, that has nothing to do with memory.

This is not very hard to prove, if you do:

 System.out.println(new Object().hashCode());

multiple times, in a new VM all the time - you will get the same value, so Marsaglia XOR-Shift starts with a seed (always the same, unless some other code does not alter it) and works from that.

But even if you switch to some hashCode that is memory based, and Objects potentially move around (Garbage Collector calls), how do you ensure that the same hashCode is taken after GC has moved this object? Hint: indentityHashCode and Object headers.

Upvotes: 36

Spandan Thakur
Spandan Thakur

Reputation: 368

The default implementation of Hashcode in object class is the object's memory address in hexadecimal. The JVM invokes the implementation of this.

Some helpful links are:

https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

Upvotes: 1

Related Questions