Skip to main content
Advertisement

9.1 The Object Class

Note: This guide is written based on Java 21. For the most up-to-date details, please refer to the official Java Documentation.

In Java, whenever you create a class, a hidden inheritance automatically occurs. Unless a programmer explicitly uses the extends keyword to inherit from a different parent class, every class in Java implicitly inherits from the java.lang.Object class.

Consequently, every object in Java is a descendant of this Object class, meaning you can universally call any of the 11 fundamental methods provided by Object. In this chapter, we will summarize the three most core and widely-used methods among them.

1. Returning Object Information as a String: toString()

The toString() method returns brief information about the instantiated object as a String.

You've probably noticed that when you run System.out.println(ObjectName), a confusing combination of letters and numbers prints out (e.g., Person@15db9742). This happens because println() automatically invokes the object's toString() method behind the scenes.

By default, the Object class's toString() is designed to return ClassName@HexadecimalHashcode. However, when designing a class, programmers typically override this method to output meaningful, human-readable information about that specific object.

class Book {
String title;
String author;

Book(String title, String author) {
this.title = title;
this.author = author;
}

// Overriding the toString() method from the Object class
@Override
public String toString() {
return "Book Title: " + title + ", Author: " + author;
}
}

public class ObjectExample {
public static void main(String[] args) {
Book myBook = new Book("Java Standard", "Namgung Sung");
// myBook.toString() gets called automatically here
System.out.println(myBook);
}
}

[Execution Result]

Book Title: Java Standard, Author: Namgung Sung

2. Comparing the Contents of Objects: equals(Object obj)

Imagine you have two identical-looking objects in Java, much like twins. If you compare these two objects using the == operator, Java will reply with false 100% of the time, because == strictly checks if they occupy the literal same "memory address" (they are houses built on different physical lots).

If you want to compare "whether the contents (data) inside are identical," you must use the equals() method. However, since the default implementation of equals() in the Object class also just uses == for address comparison, programmers must override it based on their own criteria!(The primary reason we always use equals() to compare text in the String class is exactly because String has already overridden this method internally to return true if the text characters match.)

class User {
long id; // Social Security Number or unique ID

User(long id) {
this.id = id;
}

// Overriding Object's equals() to compare contents instead
@Override
public boolean equals(Object obj) {
// Is the comparison target safely castable to a User type?
if (obj instanceof User) {
User other = (User) obj;
return this.id == other.id; // Returns true if the IDs match
}
return false;
}
}

public class EqualsExample {
public static void main(String[] args) {
User u1 = new User(8001011111111L);
User u2 = new User(8001011111111L);

System.out.println(u1 == u2); // false (different memory addresses)
System.out.println(u1.equals(u2)); // true (due to overridden evaluation logic)
}
}

3. An Object's Unique Number: hashCode()

The hashCode() method returns a single, unique integer value (a hash code) used to identify an object. The Java system primarily uses this as a 'Key' to maximize data retrieval speed when storing objects in data structures like HashMap and HashSet.

  • Generally, the default function in Object generates this hash code based on the physical memory address.
  • Critical Rule: If you override the equals() method to define "these two objects are functionally the same," you absolutely must also override hashCode() to tell the Java system, "these two identical objects yield exactly the same hash code number." (Failing to do so will cause massive bugs in Collection Framework data structures later!)

In summary, Java's ultimate ancestor, the Object class, serves as an incredibly useful toolbox assembling the skeletal foundations for essential operations like "identification, string representation, and comparison" required throughout programming.

Advertisement