The Object Class
The Object class in java.lang is the root of the class hierarchy. Every class in Java implicitly extends Object, making its methods available to all objects.
The Root of All Classes
Every class in Java, whether you explicitly extend it or not, is a descendant of Object:
// These two declarations are equivalent:
class MyClass { }
class MyClass extends Object { }
// Even classes that extend other classes ultimately extend Object
class Animal { } // Implicitly extends Object
class Dog extends Animal { } // Dog -> Animal -> Object
toString()- String representation of the objectequals(Object obj)- Check if two objects are equalhashCode()- Return a hash code valuegetClass()- Return the runtime classclone()- Create a copy of the objectfinalize()- Called before garbage collection (deprecated)
The toString() Method
Returns a string representation of the object. The default implementation returns the class name followed by @ and the hash code in hexadecimal.
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Person p = new Person("Alice", 25);
System.out.println(p); // Output: Person@1a2b3c4d (unhelpful!)
// Override toString() for meaningful output
class Person {
String name;
int age;
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
System.out.println(p); // Output: Person{name='Alice', age=25}
toString() in your classes for easier debugging and logging.
The equals() Method
The default equals() compares object references (same as ==). Override it to compare object content instead.
class Person {
String name;
int age;
// Default equals() compares references
Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);
System.out.println(p1 == p2); // false (different objects)
System.out.println(p1.equals(p2)); // false (default equals = ==)
// Override equals() to compare content
@Override
public boolean equals(Object obj) {
if (this == obj) return true; // Same reference
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
}
The hashCode() Method
Returns an integer hash code value for the object. If you override equals(), you must override hashCode() too.
- If
a.equals(b)is true, thena.hashCode() == b.hashCode()must be true - If
hashCode()values are different,equals()must return false - Two unequal objects may have the same hash code (collision)
class Person {
String name;
int age;
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
// Or use Objects.hash() (Java 7+)
@Override
public int hashCode() {
return java.util.Objects.hash(name, age);
}
}
The getClass() Method
Returns the runtime class of the object. This method is final and cannot be overridden.
Animal animal = new Dog();
Class<?> cls = animal.getClass();
System.out.println(cls.getName()); // "Dog"
System.out.println(cls.getSimpleName()); // "Dog"
System.out.println(cls.getSuperclass()); // "class Animal"
Click Run to execute your code
The clone() Method
Creates and returns a copy of the object. To use it, your class must implement Cloneable interface.
class Person implements Cloneable {
String name;
int age;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // Shallow copy
}
}
Person original = new Person("Alice", 25);
Person copy = (Person) original.clone();
System.out.println(original == copy); // false (different objects)
System.out.println(original.name == copy.name); // true (shallow copy!)
- Shallow copy: Copies references (default clone behavior)
- Deep copy: Creates new instances of referenced objects too
Complete Example: Proper equals/hashCode/toString
import java.util.Objects;
class Student {
private String name;
private int id;
public Student(String name, int id) {
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "Student{name='" + name + "', id=" + id + "}";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, id);
}
}
Common Mistakes
- Overriding equals() without hashCode(): Breaks HashMap, HashSet functionality
- Using == instead of equals() for strings: Always use
.equals()for object comparison - Not checking for null in equals(): Can cause NullPointerException
- Forgetting to override toString(): Makes debugging difficult
Summary
Objectis the root class - every class extends it- Override
toString()for meaningful string representation - Override
equals()to compare object content (not references) - If you override
equals(), always overridehashCode() getClass()returns the runtime class (cannot be overridden)clone()creates a copy (requires Cloneable interface)
Enjoying these tutorials?