Object Class in Java
In the realm of Java programming, the
Object
class holds a special place, it's the root of the class hierarchy, and every class in Java implicitly inherits from it.As a result, the
Object
class comes equipped with several crucial methods that lay the foundation for effective object-oriented programming.
equals()
Method
The
equals()
method is the linchpin for object comparison. By default, it compares object references, checking if two references point to the same object in memory.However, in many scenarios, we need to customize this method to compare objects based on their attributes.
Let's take a look at an example using a
Person
class:
class Person {
private String name;
private int age;
// Constructor and other methods
@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);
}
}
In this example, we override equals()
to compare Person
objects based on their name
and age
attributes.
hashCode()
Method
The
hashCode()
method is crucial when dealing with collections likeHashMap
orHashSet
.It generates a unique integer representation of an object.
It is good practice to override
hashCode()
when customizing theequals()
method to maintain the contract that equal objects must have equal hash codes.Continuing with our
Person
class:
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
Here, we generate a hash code based on the name
and age
attributes. The multiplication by 31 is a common practice to avoid collisions and improve distribution.
toString()
Method
The
toString()
method provides a string representation of the object.While the default implementation includes the class name and hash code, it is often beneficial to override this method for more meaningful output.
Let's enhance our
Person
class with a customtoString()
method:
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
This toString()
method generates a string with the person's name
and age
attributes, making it easier to understand the object's state.
clone()
Method
The
clone()
method is used to create and return a copy of the object.To use
clone()
, the class must implement theCloneable
interface. Let's modify ourPerson
class:
class Person implements Cloneable {
// ... existing code ...
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Now, you can create a copy of a Person
object using the clone()
method.
finalize()
Method
The
finalize()
method is called by the garbage collector before an object is reclaimed.It can be overridden for cleanup operations, but it is generally not recommended due to its uncertain execution.
Here's an example:
class Person {
// ... existing code ...
@Override
protected void finalize() throws Throwable {
// Cleanup operations
super.finalize();
}
}
This method is not commonly used in modern Java programming.
getClass()
Method
The
getClass()
method returns the runtime class of the object.It is useful for obtaining information about the type of an object:
Person person = new Person("Alice", 30);
Class<?> personClass = person.getClass();
System.out.println("Class of Person: " + personClass.getName());
This is often used for reflection and obtaining runtime class information.
notify()
and notifyAll()
Methods
These methods are used in multithreading to notify waiting threads about changes in the object's state.
Here's a snippet of code demonstrating their usage:
class SharedResource {
synchronized void performOperation() {
// Perform some operation
notify(); // Notify one waiting thread
// or
// notifyAll(); // Notify all waiting threads
}
}
They are commonly used in synchronization scenarios when multiple threads are interacting with shared resources.
wait()
Method
The
wait()
method causes the current thread to wait until another thread callsnotify()
ornotifyAll()
on the object.Here's a simple example:
class SharedResource {
synchronized void waitForSignal() throws InterruptedException {
wait();
}
}
It is used in coordination between threads.