Object Class, Cloneable & Comparable — Inherited Tools

Object ক্লাস, Cloneable ও Comparable — উত্তরাধিকারে পাওয়া টুল

Read: ~28 min Intermediate 5 practice problems Live code runner

1. What Every Java Object Knows How To Do

Every class silently inherits a handful of methods from java.lang.Object. You have already met equals, hashCode, and toString. There are more — getClass, clone, finalize, wait/notify. Two marker interfaces in the standard library — Cloneable and Comparable — turn some of these into contract points your class can opt into.

প্রতিটি Java class নীরবে java.lang.Object থেকে কিছু method পায় — equals, hashCode, toString ছাড়াও getClass, clone, wait/notify। Cloneable ও Comparable — দুটি marker interface-এ opt-in করে নির্দিষ্ট আচরণ পাওয়া যায়।

2. The Object Methods Cheat Sheet

MethodWhat it doesUsually override?
equals(Object)Value equality.Yes (for data classes).
hashCode()Bucket index for hash collections.Yes, with equals.
toString()Human-readable form.Yes, for logs/debug.
getClass()Runtime Class metadata.No — final.
clone()Shallow copy — only if Cloneable.Avoid; use a copy constructor.
wait/notifyLow-level thread coordination.No — use concurrency utilities.
finalize()Pre-GC cleanup (deprecated).No — use try-with-resources.

3. Cloneable — Broken by Design; Use a Copy Constructor

Joshua Bloch in Effective Java famously calls the Cloneable mechanism "interface without a method" and recommends never using it. The replacement is trivial: write a copy constructor or a static copyOf factory.

Main.java
class Address {
    String city;
    Address(String city) { this.city = city; }
    // Copy constructor
    Address(Address other) { this.city = other.city; }
}

class Main {
    public static void main(String[] args) {
        Address a = new Address("Dhaka");
        Address b = new Address(a);       // clean copy — no Cloneable drama
        b.city = "Chattogram";
        System.out.println(a.city + " vs " + b.city);
    }
}
Cloneable বহু সমস্যায় পরিপূর্ণ — Object.clone() protected, CloneNotSupportedException, shallow vs deep copy, constructor চলে না। এর বদলে copy constructor বা static copyOf factory ব্যবহার করুন — সহজ, স্পষ্ট, নিরাপদ।

4. Comparable<T> — Natural Ordering

Implement Comparable<T> when your class has one obvious sort order — chronological for dates, alphabetical for names, numeric for money. Then Collections.sort, TreeSet, and TreeMap work with it out of the box.

Main.java
import java.util.*;

class Student implements Comparable<Student> {
    String name; double cgpa;
    Student(String n, double c) { name = n; cgpa = c; }

    @Override public int compareTo(Student other) {
        return Double.compare(other.cgpa, this.cgpa);  // higher CGPA first
    }

    @Override public String toString() { return name + "(" + cgpa + ")"; }
}

class Main {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>(List.of(
            new Student("Sumi",  3.7),
            new Student("Rahim", 3.9),
            new Student("Faria", 3.6)
        ));
        Collections.sort(list);
        System.out.println(list);
    }
}
compareTo contract: return a negative int if this < other, zero if equal, positive if greater. Always use Integer.compare, Double.compare, etc. — never raw subtraction, because it overflows.

5. Comparator<T> — Custom Ordering on the Fly

If there is no single "natural" order, or you want to sort by something else for this particular call, use a Comparator. Modern Java makes this delightful:

Main.java
import java.util.*;

class Product {
    String name; double price;
    Product(String n, double p) { name = n; price = p; }
    @Override public String toString() { return name + "@" + price; }
}

class Main {
    public static void main(String[] args) {
        List<Product> cart = new ArrayList<>(List.of(
            new Product("Rice 5kg", 650),
            new Product("Lentil 1kg", 160),
            new Product("Oil 5L", 900)
        ));

        cart.sort(Comparator.comparingDouble(p -> p.price));    // cheap → expensive
        System.out.println(cart);

        cart.sort(Comparator.comparingDouble((Product p) -> p.price).reversed()
                            .thenComparing(p -> p.name));
        System.out.println(cart);
    }
}

6. Vocabulary (শব্দভাণ্ডার)

TermMeaningবাংলায়
ObjectRoot class; parent of every Java class.সব class-এর root।
clone()Shallow-copy method on Object (protected).Object-এর shallow copy method।
CloneableMarker interface enabling clone(); avoided in modern Java.Marker interface — আধুনিক Java-তে পরিহার্য।
Copy constructorRecommended alternative to clone().Clone-এর recommended বিকল্প।
Comparable<T>"This type has a natural order."Type-এর একটি natural order আছে।
compareToReturns <0, 0, >0 to sort against another instance.<0, 0, >0 ফেরত দেয়।
Comparator<T>External ordering strategy passed to sort.বাহ্যিক ordering strategy।

7. Practice Problems

  1. Write a Book class implementing Comparable<Book> so books sort alphabetically by title.
    Book class তৈরি করুন — title-এ alphabetical order-এ sort হবে।
    ✨ Show Answer
    Main.java
    import java.util.*;
    class Book implements Comparable<Book> {
        String title;
        Book(String t) { title = t; }
        @Override public int compareTo(Book o) { return title.compareTo(o.title); }
        @Override public String toString() { return title; }
    }
    class Main {
        public static void main(String[] args) {
            List<Book> bs = new ArrayList<>(List.of(
                new Book("Padma Nadir Majhi"),
                new Book("Lal Shalu"),
                new Book("Aagun Pakhi")));
            Collections.sort(bs);
            System.out.println(bs);
        }
    }
  2. Given a list of strings, sort them by length using a Comparator without implementing Comparable.
    Comparable ছাড়াই Comparator দিয়ে কিছু string-কে দৈর্ঘ্য অনুযায়ী sort করুন।
    ✨ Show Answer
    Main.java
    import java.util.*;
    class Main {
        public static void main(String[] args) {
            List<String> cities = new ArrayList<>(List.of("Dhaka", "Chattogram", "Sylhet", "Cox"));
            cities.sort(Comparator.comparingInt(String::length));
            System.out.println(cities);
        }
    }
  3. In 2 sentences: why is return a.value - b.value; a dangerous compareTo body for ints?
    দুই বাক্যে — return a.value - b.value; int তুলনায় কেন বিপজ্জনক?
    ✨ Show Answer

    Answer: When the values span a large range (e.g., one near Integer.MAX_VALUE and one negative), the subtraction can overflow and silently flip sign — breaking the ordering in just one tricky case. Use Integer.compare(a, b) instead; it handles the edge cases correctly.

    Subtraction overflow করলে sign উল্টে যেতে পারে এবং ordering ভেঙে পড়ে — কেবল নির্দিষ্ট কিছু মানে। Integer.compare নিরাপদ।

  4. Write a copy constructor for a class Person with a String name and an Address (Address already shown above). Modify the copy's city and prove the original is untouched.
    Person class-এর জন্য copy constructor লিখুন — name String এবং Address। Copy-এর city বদলে দেখান original একই আছে।
    ✨ Show Answer
    Main.java
    class Address {
        String city;
        Address(String c) { city = c; }
        Address(Address o) { city = o.city; }
    }
    class Person {
        String name;
        Address addr;
        Person(String n, Address a) { name = n; addr = a; }
        Person(Person o) { name = o.name; addr = new Address(o.addr); }  // deep copy
    }
    class Main {
        public static void main(String[] args) {
            Person p = new Person("Raju", new Address("Dhaka"));
            Person q = new Person(p);
            q.addr.city = "Khulna";
            System.out.println(p.addr.city + " vs " + q.addr.city);
        }
    }
  5. Name two concrete reasons Joshua Bloch advises against implementing Cloneable.
    Joshua Bloch কেন Cloneable এড়াতে বলেন — দুটি নির্দিষ্ট কারণ।
    ✨ Show Answer

    Answer:

    • Object.clone() bypasses the constructor, so any invariants you enforce in your constructor can be silently violated.
    • The default clone() is shallow — cloned objects share references to inner mutable objects, creating subtle aliasing bugs. Correct deep-cloning code is fragile and easy to get wrong as the class evolves.

    Clone constructor bypass করে — তাই invariants ভেঙে যেতে পারে; এছাড়া shallow copy — inner mutable object share হয়ে aliasing bug তৈরি করে।

Summary — Module 20

Every Java class inherits a handful of methods from Object — and three of them (equals, hashCode, toString) you almost always want to override. Cloneable and Object.clone() are legacy and widely regarded as broken — use a copy constructor or static copyOf factory instead. Implement Comparable<T> when your class has one natural sort order, and use Comparator<T> for everything else; modern Comparator.comparing plus thenComparing makes multi-key sorting a one-liner.

প্রতিটি Java class Object থেকে কিছু method পায় — equals, hashCode, toString সাধারণত override করা হয়। Cloneable পুরনো ও "broken" — বরং copy constructor বা static copyOf ব্যবহার করুন। Natural ordering-এর জন্য Comparable, বাহ্যিক বা ভিন্ন ordering-এর জন্য Comparator (comparing + thenComparing)।

Next Module → Generics — type-safe code with type parameters এবং wildcards।