Object Class in Java
In Java, the Object class resides within the java.lang package. It serves as a foundation for all classes, directly or indirectly. If a class doesn't extend any other class, it's a direct child of Object; if it extends another class, it's indirectly derived. Consequently, all Java classes inherit the methods of the Object class, making it the cornerstone of inheritance hierarchy in Java programs.
Object Class Methods
There are various methods of the Object class. They are inherited by other classes.
1. toString() Method
The toString() method in Java furnishes a String representation of an object, converting it into a human-readable format. By default, the toString() method in the Object class generates a string comprising the class name of the object, an '@' symbol, and the object's hexadecimal hash code.
Take a look at this example-
Output
Explanation
Here we can see that when we tried to print the string representation of car_no using toString() method and print statement, it printed its hexadecimal representation. It was not the desired result. So, here we have to override the toString() method so that we get the exact value as a string that the variable has stored.
This is how we can do it.
Output
Explanation
Here, we can see that after overriding, we get the desired output.
2. hashCode() Method
A hash code is an integer value that gets generated by the hashing algorithm. Hash code is associated with each object in Java and is a distinct value. It converts an object's internal address to an integer through an algorithm. It is not the memory address, it is the integer representation of the memory address.
Another point to be noted is that this method is a Native method. A native method allows us to use code from another language like C, or C++ in Java. In Java, we cannot find the memory address of objects, so the hashCode() method is written in C or C++ which fetches the object's address in Java.
Syntax
Let us look at this example.
Output
The above code shows the default behavior of the hashCode() method. Here we have not overridden the hashCode() method.
It's essential to override the hashCode() method to ensure that each object produces a distinct number. Let us look at that implementation.
Example
Output
Explanation
We can see that after we override, hashCode() method returns unique values.
3. equals (Object obj) Method
This method compares two objects and returns whether they are equal or not. It is used to compare the value of the object on which the method is called and the object value which is passed as the parameter.
It is usually recommended to override the hashCode() method whenever this method is overridden, as it'll ensure that equal objects must have equal hash codes.
Example
Explanation
The default implementation checks whether the two objects i.e., the object on which the method is called and the obj object are equal or not. Here equal means whether they are referring to the same object. If they are the same, it returns true, else it returns false.
4. getClass() Method
It is used to return the class object of this object. Also, it fetches the actual runtime class of the object on which the method is called. This is also a native method. It can be used to get the metadata of the this class. Metadata of a class includes the class name, fields name, methods, constructor, etc.
Example
Output
Explanation
In the above example, we fetched the runtime classes of a string and an integer. For the string, the class was java.lang.String whereas, for the integer, the class was java.lang.Integer.
5. finalize() method
Just before Java's garbage collector reclaims an object, the finalize() method is invoked, ensuring a last chance for any necessary cleanup tasks when no references to the object remain. It offers a chance to perform cleanup tasks and release system resources, thereby reducing memory leaks. For instance, in web applications, it's common practice to use finalize() to clean up session-related resources in Servlet objects before they are destroyed by the container. It's important to note that finalize() is called only once on an object, even if it's eligible for garbage collection multiple times.
Output:
6. clone() Method
The clone() method is used to create an exact copy of this object. It makes a new object and copies all the data of the this object to the new object.
Example
Output
Explanation
In the above code, we have cloned an object and then printed its value. We have made the Main class implement the Cloneable interface as, if we don't do it it will throw an exception of CloneNotSupportedException. We first created an object obj1 and then we cloned it using the clone() method. Then we printed both the objects and hence it gets verified that both the objects are the same.
7. wait() Method
The wait() method instructs the current thread to release its lock and enter a sleeping state. It happens until some different thread enters the same monitor and calls the methods like notify() or notifyAll() method.
8. notify() Method
The notify() method is used to wake up only one single thread that is waiting on the object, and that thread starts the execution. If multiple threads are waiting on the current object (this), the notify() method will awaken one of them arbitrarily. This method does not return any value.
Before proceeding with the example, let us know what threads are. A thread represents the execution path of a program, determining the sequence of instructions executed within it. Every Java program initiates with a primary thread, referred to as the main thread, which the Java Virtual Machine (JVM) spawns upon invoking the main() method during program startup.
Example
Here we have also used the wait() method which is discussed in the later section.
Output
Explanation
Firstly, we have used the synchronized block to ensure that only one thread is running at a time.
We create 3 classes that extend the Thread class. Then we use the wait() block. We use the try-and-catch block to catch an exception. In the main function, we create the objects of the above classes and then create the threads. Then we call the run method.
9. notifyAll() Method
The notifyAll() method awakens all threads currently waiting on the object instance where it's invoked.
It will execute all the threads individually. All threads get the notification but only one thread gets a lock. A lock serves as a mechanism to regulate access to a shared resource by multiple threads simultaneously. So only one thread proceeds with the execution at a time after that next one will be executed.
Example
Output
Explanation
The above example is similar to that of the notify() example. We have called the notifyAll() method in the Notify3 class. All the threads get created and also get notified individually.
Method | Description |
---|---|
public final Class getClass() | Retrieves the Class object associated with the instance. |
public int hashCode() | Computes and returns a unique hash code for this object. |
public boolean equals(Object obj) | Determines whether this object is equal to another object. |
protected Object clone() | Generates and provides a shallow copy of this object. |
public String toString() | Offers a string representation of this object. |
public final void notify() | Awakens a single thread waiting on this object. |
public final void notifyAll() | Awakens all threads waiting on this object. |
public final void wait(long timeout) throws InterruptedException | Directs the current thread to wait until another thread triggers the notify() or notifyAll() method for this object. |
public final void wait(long timeout, int nanos) throws InterruptedException | Instructs the current thread to wait until another thread invokes the notify() or notifyAll() method for this object. |
public final void wait() throws InterruptedException | Prompts the current thread to wait until another thread invokes the notify() or notifyAll() method for this object. |
protected void finalize() throws Throwable | Executes when the garbage collector identifies no more references to the object, signaling its readiness for collection. |
Conclusion
- The Object class in Java serves as the foundation for all classes, directly or indirectly.
- All Java classes inherit methods from the Object class, making it the root of the inheritance hierarchy.
- Key methods of the Object class include toString(), hashCode(), equals(), clone(), getClass(), finalize(), wait(), notify(), and notifyAll().
- Overriding methods like toString() and hashCode() allows customization of behavior for specific classes.
- The finalize() method provides an opportunity for cleanup tasks before an object is garbage collected.
- Understanding and utilizing Object class methods are essential for effective Java programming and memory management.