Java Object

Summary: in this tutorial, you will learn about Java Object which serves as the base class for all classes in Java.

Introduction to Java Object

The java.lang.Object class is the base class of all classes in Java.

It means that when you define a class, it is implicitly a subclass of the Object class. Also, the class automatically inherits a set of methods from the Object class.

Suppose that you have a Person class with two fields ssn and name, and a constructor:

class Person {
    private String ssn;
    private String name;

    // Getters and setters (omitted for brevity)

    public Person(String ssn, String name){
        this.ssn = ssn;
        this.name = name;
    }
}Code language: Java (java)

It is like defining the Person class that extends the Object class:

class Person extends Object {
   // ...
}Code language: Java (java)

However, it is not necessary since Java does it implicitly for us.

We’ll explore the methods provided by the Object class and demonstrate how to override them to enhance the utility of your class.

Java Object methods

1) getClass()

The getClass() method returns the runtime class of an object:

var cls = obj.getClass();Code language: Java (java)

In this syntax, the cls is an instance of the java.lang.Class class.

Typically, you use the getClass() method to check if two objects are instances of the same class.

If the getClass() method of two objects returns the same value, they are instances of the same class.

For example, the following shows the return value of the getClass() method of a Person object:

public class App {
    public static void main(String[] args) {
        var person = new Person(
                "212-15-8397",
                "John Doe"
        );
        System.out.println(person.getClass());
    }
}Code language: Java (java)

Output:

class PersonCode language: Java (java)

2) equals(Object obj)

By default, the equals() method returns true if two variables reference the same object.

Typically, you override the equals() method to compare two objects by their contents.

The following example creates two Person objects with the same ssn and name, and uses the equals() method to compare them:

public class App {
    public static void main(String[] args) {
        var p1 = new Person("212-15-8397", "John Doe");
        var p2 = new Person("212-15-8397", "John Doe");
        var result = p1.equals(p2);
        System.out.println(result);
    }
}Code language: Java (java)

Output:

falseCode language: Java (java)

Since the Person class inherits the equals() method from the Object class, the equals() method checks if two variables reference the same object:

The program displays false because p1 and p2 variables reference different Person objects even though they have the same ssn and name values.

import java.util.Objects;

class Person {
    private String ssn;
    private String name;

    // Getters and setters (omitted for brevity)

    public Person(String ssn, String name) {
        this.ssn = ssn;
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {

        if (this == obj) return true;

        if (obj == null || obj.getClass() != getClass()) {
            return false;
        }

        Person other = (Person) obj;

        return ssn.equals(other.ssn) && name.equals(other.name);

    }
}Code language: Java (java)

In this Person class, we override the equals() method of the Object class that returns true if all the fields of the of the Person objects are equal.

First, check if the object being compared is the same as the current instance and return true if they are the same reference:

if (this == obj) return true;Code language: Java (java)

Second, return false if the object being compared is null or if its class differs from the class of the current instance:

if (obj == null || obj.getClass() != getClass()) {
   return false;
}Code language: Java (java)

Third, compare the ssn and name fields of the object being compared with the current instance and return true if they are equal:

return ssn.equals(other.ssn) && name.equals(other.name);Code language: Java (java)

Now, if two Person objects have the same ssn and name, they should be equal when you compare them using the equals() method:

public class App {
    public static void main(String[] args) {
        var p1 = new Person("212-15-8397", "John Doe");
        var p2 = new Person("212-15-8397", "John Doe");

        var result = p1.equals(p2);

        System.out.println(result); // true
    }
}Code language: Java (java)

3) hashCode()

The hashCode() method returns a unique integer that represents an object. If two objects are equal, they should have the same hash code.

Therefore, if you override the equals() method, you should also override the hashcode() method.

To generate a hash code for a sequence of input values, you can use the static method hash() of the Objects class from java.util package.

Here’s the modified version of the Person class that includes a hashCode method:

import java.util.Objects;

class Person {
    private String ssn;
    private String name;

    // Getters and setters (omitted for brevity)

    public Person(String ssn, String name) {
        this.ssn = ssn;
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {

        if (this == obj) return true;

        if (obj == null || obj.getClass() != getClass()) {
            return false;
        }

        Person other = (Person) obj;

        return ssn.equals(other.ssn) && name.equals(other.name);

    }

    @Override
    public int hashCode() {
        return Objects.hash(ssn, name);
    }
}Code language: Java (java)

The following displays the hash codes of the p1 and p2 objects:

public class App {
    public static void main(String[] args) {
        var p1 = new Person("212-15-8397", "John Doe");
        var p2 = new Person("212-15-8397", "John Doe");

        var result = p1.equals(p2);

        System.out.println(result); // true

        System.out.println(p1.hashCode());
        System.out.println(p2.hashCode());

    }
}Code language: Java (java)

Output:

true
-1693213186
-1693213186Code language: Java (java)

4) toString()

The toString() method returns a string representation of an object. The following displays the default string representation of a Person object:

public class App {
    public static void main(String[] args) {
        var person = new Person(
                "212-15-8397",
                "John Doe"
        );
        System.out.println(person);
    }
}Code language: Java (java)

Output:

Person@9b139dfeCode language: Java (java)

When we pass the Person object to the println() method, it invokes the toString() method of the Person object and displays the resulting string on the screen.

As you can see clearly from the output, the default return value of the toString() is not human-readable.

Usually, you override the toString() method to provide the human-readable string representation of the object. For example:

import java.util.Objects;

class Person {
    private String ssn;
    private String name;

    // Getters and setters (omitted for brevity)

    public Person(String ssn, String name) {
        this.ssn = ssn;
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {

        if (this == obj) return true;

        if (obj == null || obj.getClass() != getClass()) {
            return false;
        }

        Person other = (Person) obj;

        return ssn.equals(other.ssn) && name.equals(other.name);

    }

    @Override
    public int hashCode() {
        return Objects.hash(ssn, name);
    }

    @Override
    public String toString() {
        return "Person{" +
                "ssn='" + ssn + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}Code language: Java (java)

In this example, we override the toString() method of the Person class to display all the field names and values.

If you run the program that displays a Person object on the screen, you’ll see something like this:

Person{ssn='212-15-8397', name='John Doe'}Code language: Java (java)

clone() & finalize()

The Object class also has the following methods:

  • clone(): This method creates a shallow copy of an object
  • finalize(): This method performs the cleanup operations.

In practice, you’ll rarely use these methods so we don’t cover them in this tutorial.

Summary

  • In Java, every class is a subclass of the java.lang.Object class.
  • The Java Object class provides a number of useful methods for overriding in the subclass including equals(), hashCode(), and toString().
  • Override equals() and hashCode() to provide logic for comparing two objects by their contents.
  • Override toString() method to provide a meaningful string representation of an object.
  • Use the getClass() method to check the object’s type at runtime.