Checked vs Unchecked Exceptions
In Java, exceptions are categorized into Checked and Unchecked based on compile-time checking. Understanding this difference is crucial for writing robust and error-free programs.
📌 Checked Exceptions
Checked exceptions are exceptions that are checked at compile-time. The compiler ensures that these exceptions are either caught using try-catch blocks or declared in the method signature using the throws keyword. If not handled properly, the code will not compile.
Examples: IOException, SQLException, FileNotFoundException, ClassNotFoundException.
⚡ Unchecked Exceptions
Unchecked exceptions are exceptions that are checked at runtime only. They are also called RuntimeExceptions. The compiler does not enforce handling of these exceptions, making them optional to catch or declare.
Examples: NullPointerException, ArithmeticException, ArrayIndexOutOfBoundsException, NumberFormatException.
| Basis | Checked Exception | Unchecked Exception |
|---|---|---|
| Checking Time | Compile-time | Runtime |
| Handling Requirement | Must handle or declare (mandatory) | Optional to handle |
| Parent Class | java.lang.Exception (excluding RuntimeException) | java.lang.RuntimeException |
| Recovery | Possible to recover (e.g., file not found → try alternative) | Difficult to recover (programmer error) |
| Examples | IOException, SQLException, InterruptedException | NullPointerException, ArithmeticException, IllegalArgumentException |
📝 Code Examples:
Checked Exception Example:
import java.io.*;
public class CheckedExceptionDemo {
public static void main(String[] args) {
try {
FileReader file = new FileReader("test.txt");
BufferedReader br = new BufferedReader(file);
String data = br.readLine();
System.out.println(data);
} catch (IOException e) {
System.out.println("File not found!");
}
}
}
Unchecked Exception Example:
public class UncheckedExceptionDemo {
public static void main(String[] args) {
int a = 10;
int b = 0;
// This will throw ArithmeticException at runtime
int result = a / b;
System.out.println(result);
}
}
Comparable vs Comparator
Both Comparable and Comparator are interfaces used to compare objects in Java for sorting, but they differ in how and where they define comparison logic. Understanding these differences is essential for effective sorting in Java Collections.
📊 Comparable Interface
The Comparable interface belongs to the java.lang package and defines the natural ordering of objects. The class itself implements the compareTo() method to determine the order. This provides a single sorting sequence (default ordering).
🎛️ Comparator Interface
The Comparator interface belongs to the java.util package and is used for custom ordering. You implement the compare() method in a separate class without modifying the original class. This allows multiple sorting sequences.
| Basis | Comparable | Comparator |
|---|---|---|
| Package | java.lang | java.util |
| Method to Implement | compareTo(Object obj) | compare(Object obj1, Object obj2) |
| Sorting Logic | Inside the same class (modifies original) | In a separate class (doesn't modify original) |
| Number of Sort Orders | Only one (natural ordering) | Multiple (custom ordering possible) |
| Usage | Collections.sort(list) | Collections.sort(list, comparator) |
| Example Use Case | Student sorting by roll number (default) | Student sorting by name, age, marks (custom) |
📝 Code Examples:
Comparable Example (Natural Ordering):
class Student implements Comparable<Student> {
int rollno;
String name;
Student(int rollno, String name) {
this.rollno = rollno;
this.name = name;
}
public int compareTo(Student s) {
// Natural ordering by roll number
return this.rollno - s.rollno;
}
}
// Usage
Collections.sort(studentList);
Comparator Example (Custom Ordering):
// Custom comparator for sorting by name
class NameComparator implements Comparator<Student> {
public int compare(Student s1, Student s2) {
return s1.name.compareTo(s2.name);
}
}
// Custom comparator for sorting by roll number (reverse)
class RollComparator implements Comparator<Student> {
public int compare(Student s1, Student s2) {
return s2.rollno - s1.rollno;
}
}
// Usage
Collections.sort(studentList, new NameComparator());
Java 8 Lambda Example (Comparator):
// Using lambda expression for comparator Collections.sort(studentList, (s1, s2) -> s1.name.compareTo(s2.name)); // Using Comparator.comparing Collections.sort(studentList, Comparator.comparing(s -> s.name));
When to Use What?
✅ Use Comparable when:
• You have a natural/default ordering
• You can modify the class
• Only one sorting sequence is needed
• The class has a logical ordering (e.g., roll numbers, dates)
✅ Use Comparator when:
• You cannot modify the class
• Multiple sorting sequences are needed
• You want different sorting criteria (by name, age, marks)
• You want reverse/descending order