In this article, we’ll have a comprehensive look at the Java object class, a fundamental component of Java programming. Object class is the root of the class hierarchy. we’ll learn with examples for better understanding. So let’s get started
Introduction
In Java, object class is at the top of the class hierarchy. Every class in Java is considered as a subclass of the ‘Object‘ class. This root class is a part of ‘ java.lang ‘ package. This package is automatically imported into every Java source file, which means you no need to explicitly import the package using the ‘import‘ statement.
Methods provided by object class
1) clone():
- Purpose: Creates and returns a copy of the object.
- This method performs a shallow copy of the object. To use this method, the class must implement the ‘Cloneable’ interface otherwise, it throws a ‘CloneNotSupportedException’. A shallow copy means that it copies the object’s fields as they are, but if the object contains references to other objects, those references are copied rather than the objects themselves.
2) hashCode():
- Purpose: Returns an integer hash code that represents the object.
- This method is used in hashing-based collections like HashMap and HashSet to quickly locate objects. The hash code helps in determining the bucket location of the object. The method should be overridden to provide a meaningful hash code based on the object data. So objects with same object data have the same hash code. we use equals() method to find that two objects are same.
3) toString():
- Purpose: Returns a string representation of the object.
- By default, this method returns a string that consists of the class name followed by the object’s hash code in hexadecimal. By Overriding this method allows you to provide a more useful and readable description of the object, often including the values of its fields.
4) getClass():
- Purpose: Returns the runtime class of the object.
- This method provides a Class object that represents the type of the object at runtime. This is useful when you want to learn more about the object’s structure, such as its methods or fields, without knowing its type beforehand. It’s useful for reflection, where you need to examine or manipulate the properties of the class.
5) equals():
- Purpose: Checks if this object is equal to another object.
- Details: By default, it checks if two objects are the exact same instance. However, it’s often overridden to compare the actual data inside the objects. This way, two different instances with the same content can be considered equal.
6) finalize():
- Purpose: Allows to clean up resources before the object is destroyed by the garbage collector.
- This method provides an opportunity to clean up resources before the object is garbage collected. However, Generally finalize() method is not recommended because it can be unpredictable and slow. It’s hard to know when the garbage collector will run, so you can’t rely on finalize() method to clean up resources in a timely manner.. It’s better to use other resource management techniques, like try-with-resources or explicit cleanup methods.
7) wait():
- Purpose: Causes the current thread to wait until another thread invokes notify() or notifyAll() on this object.
- This method is used in synchronized blocks or methods to pause the execution of a thread until a specific condition is met. It releases the lock on the object, allowing other threads to obtain the lock and proceed. There are overloaded versions that allow waiting for a specified amount of time.
8) notify():
- Purpose: Wakes up only one thread waiting on the object and that thread starts execution.
- This method is used within synchronized blocks or methods to signal that a condition a thread is waiting for has been met. Only one of the threads waiting for the object’s monitor will be awakened.
9) notifyAll():
- Purpose: Wakes up only all threads waiting on the object and all threads starts execution.
- This method is also used within synchronized blocks or methods, but unlike notify(), it wakes up all waiting threads, allowing them to compete for the lock and proceed.
Example
import java.util.Objects; public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } // Overriding the toString() method @Override public String toString() { return "name='" + name + "', age=" + age ; } // Overriding the equals() method @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Person person = (Person) obj; return age == person.age && name.equals(person.name); } // Overriding the hashCode() method @Override public int hashCode() { return Objects.hash(name, age); } public static void main(String[] args) { // Creating two Person objects Person person1 = new Person("Alice", 30); Person person2 = new Person("Bob", 25); // Printing the objects using toString() System.out.println("Person 1: " + person1); System.out.println("Person 2: " + person2); // Testing equality using equals() System.out.println("Are they equal? " + person1.equals(person2)); // Getting the class of an object using getClass() System.out.println("Class of person1: " + person1.getClass()); } }