Skip to content

Commit 092e9b7

Browse files
committed
feat(exceptions): add notes and example on using generics with custom exceptions
WHAT: - Explained why generic exception classes like `class MyGenericException<T> extends Exception` are not allowed in Java. - Added example of `DetailedException<T>` that uses generics safely by keeping type information in fields rather than the class itself. - Demonstrated throwing and catching a `DetailedException<Integer>` with additional error details. WHY: - In Java, all exceptions extend from `Throwable`. For runtime consistency, the JVM must know the concrete exception type. - Due to **type erasure**, generic type parameters (like `<T>`) are erased at runtime, so the JVM cannot distinguish between `MyGenericException<Integer>` and `MyGenericException<String>`. - This makes generic exception instantiation impossible, but we can still use generics to enrich exception details. HOW: - Defined `class DetailedException<T> extends Exception` with a generic field `T details`. - Constructor accepts both a message (`String`) and details (`T`). - `getDetails()` returns the type-safe extra data. - Example: throwing `new DetailedException<Integer>("An error occurred", 404)` and catching it to retrieve both the message and extra detail. KEY TAKEAWAYS: 1. **Checked vs Unchecked Exceptions** - `Exception` (checked): must be declared or handled. - `RuntimeException` (unchecked): don’t need explicit declaration/handling. 2. **Restrictions with Generics** - Cannot define `class MyGenericException<T> extends Exception` → compile-time error. - Reason: **type erasure** removes `<T>` at runtime. 3. **Safe Pattern** - Store generic data inside an exception (fields), not in its type. - This allows passing extra type-safe diagnostic data while keeping exception hierarchy valid. REAL-WORLD USE CASES: - Wrapping domain-specific errors with structured details: - Example: `DetailedException<OrderId>` for invalid order references. - Example: `DetailedException<ErrorCode>` in APIs for passing numeric error codes alongside messages. - Improves debugging and error-handling workflows by attaching context data directly to exceptions. Signed-off-by: https://github.com/Someshdiwan <[email protected]>
1 parent 216a685 commit 092e9b7

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
In Java, exceptions are objects that represent an error or unexpected condition during the execution of a program.
2+
3+
All exceptions in Java are descendants of Throwable, which has two main subclasses:
4+
5+
Exception: Represents checked exceptions (those that need to be declared or handled).
6+
RuntimeException: Represents unchecked exceptions (those that don’t need to be declared or handled).
7+
Here’s an example of a basic custom exception:
8+
9+
class MyException extends Exception {
10+
public MyException(String message) {
11+
super(message);
12+
}
13+
}
14+
Understanding Generic Exceptions
15+
16+
Generics allow us to parameterize types (as discussed in earlier points).
17+
18+
The concept of generics can be applied to exceptions as well. However, generic exceptions have certain restrictions
19+
due to how Java handles exceptions.
20+
21+
Key Restriction:
22+
You cannot create instances of generic types as exceptions: The Java runtime needs to be able to construct exceptions
23+
based on the exact type. But due to type erasure (discussed later), the JVM loses the specific type information at runtime.
24+
25+
Thus, the direct usage of generic types in exceptions is limited.
26+
27+
For example, the following is not allowed:
28+
29+
class MyGenericException<T> extends Exception { // Compilation error
30+
private T data;
31+
32+
public MyGenericException(T data) {
33+
this.data = data;
34+
}
35+
}
36+
37+
This will cause a compilation error because the type T is erased at runtime, and Java can't determine what specific
38+
exception to instantiate.
39+
40+
Advanced Generic Exception Patterns:
41+
42+
Even though you can’t directly instantiate generic exceptions, there are still advanced patterns and techniques to
43+
incorporate generic behaviour in exceptions. Here’s how:
44+
45+
Using Generics with Exception Messages or Fields:
46+
47+
You can include generic types in the fields or messages of exceptions instead of trying to make the exception class
48+
itself generic.
49+
50+
Example:
51+
class DetailedException<T> extends Exception {
52+
private T details;
53+
54+
public DetailedException(String message, T details) {
55+
super(message);
56+
this.details = details;
57+
}
58+
59+
public T getDetails() {
60+
return details;
61+
}
62+
}
63+
64+
public class Main {
65+
public static void main(String[] args) {
66+
try {
67+
throw new DetailedException<Integer>("An error occurred", 404);
68+
} catch (DetailedException<Integer> e) {
69+
System.out.println(e.getMessage()); // Output: An error occurred
70+
System.out.println(e.getDetails()); // Output: 404
71+
}
72+
}
73+
}
74+
75+
In this case, the DetailedException class contains a generic field details that can hold extra information about the
76+
exception.
77+
78+
This information could be anything, such as the problematic value or other diagnostic data.

0 commit comments

Comments
 (0)