Types
Checked vs unchecked exceptions, Error vs Exception and hierarchy
The first step in good exception handling is knowing what kind of failure you are looking at: a recoverable condition, a caller mistake, an infrastructure problem, or a JVM-level failure.
1. Definition
What is an exception type?
In Java, exception types describe abnormal situations that interrupt the normal control flow of a program.
They are represented by classes in the Throwable hierarchy.
That hierarchy is not just a taxonomy.
It encodes important design signals about:
- whether callers are expected to recover
- whether the compiler enforces handling
- whether the failure is probably caused by business conditions, programmer mistakes, or system breakdown
Why does the type matter?
The concrete exception type affects:
- method signatures
- API ergonomics
- logging strategy
- retry behavior
- transaction behavior
- monitoring and alerting
- interview answers about design quality
If you choose the wrong exception type, the code may still compile, but the API becomes misleading.
That is why senior engineers treat exception types as part of the public contract, not just as error labels.
The root of the hierarchy
All throwables inherit from Throwable.
The two main branches are:
ErrorException
Inside Exception, the most important split is:
- checked exceptions
- unchecked exceptions (
RuntimeExceptionand its subclasses)
This split is the core of most Java exception-handling discussions.
2. Core Concepts
2.1 `Throwable`
2.1.1 Keywords and contracts you should state explicitly here
This topic becomes clearer if you deliberately name the hierarchy and contract words behind exception design:
Throwable— the common root type of everything that can be thrown.Error— a JVM- or environment-level failure category that application code usually does not recover from as normal flow.Exception— the application-facing branch for exceptional conditions.checked exception— an exception the compiler forces you to catch or declare.unchecked exception— aRuntimeException-based failure not enforced by method signatures.cause— the original underlying failure linked to a higher-level exception.stack trace— the recorded execution path at the point of failure.suppressed exception— a secondary failure, often from cleanup, attached to a primary exception.
These are not just labels. They communicate recovery expectations, API burden, and failure semantics.
Throwable is the common supertype of everything that can be thrown.
It carries:
- the message
- the stack trace
- the cause
- suppressed exceptions
In practice, you rarely design APIs directly around Throwable.
You usually work at a more specific level.
2.2 `Error`
Error represents serious problems that applications usually should not try to handle as ordinary business flow.
Typical examples:
OutOfMemoryErrorStackOverflowErrorNoClassDefFoundError
These often indicate:
- JVM/resource failure
- deployment/configuration issue
- corrupted runtime assumptions
A common interview point is that Error exists in the hierarchy but is generally not treated like normal application exceptions.
2.3 Checked exceptions
Checked exceptions are exceptions that the compiler forces you to either:
- catch
- or declare with
throws
Examples:
IOExceptionSQLExceptionin older APIsClassNotFoundException
Checked exceptions signal that the caller is expected to make a conscious decision.
That decision may be:
- recover
- translate
- propagate with context
The design intent is explicitness.
2.4 Unchecked exceptions
Unchecked exceptions are subclasses of RuntimeException.
Examples:
IllegalArgumentExceptionIllegalStateExceptionNullPointerExceptionIndexOutOfBoundsException
These usually signal:
- programming mistakes
- violated preconditions
- invalid state transitions
- misuse of an API
They are not enforced in method signatures.
That makes APIs simpler, but also puts more responsibility on the developer to document behavior well.
2.5 Recovery versus bug signaling
One of the strongest practical heuristics is this:
- use checked exceptions when the caller can reasonably recover
- use unchecked exceptions when the issue is usually a bug or contract violation
This rule is not perfect, but it is much better than memorizing isolated examples.
2.6 Exception hierarchy as API communication
Exception types are a form of communication.
For example:
IllegalArgumentExceptionsays the caller passed a bad valueIllegalStateExceptionsays the object is in the wrong stateUnsupportedOperationExceptionsays the operation is intentionally unavailableIOExceptionsays an external I/O boundary failed
Choosing the right type improves readability and debuggability.
2.7 Cause chains
A good exception model preserves the original cause.
throw new IllegalStateException("Failed to load user profile", ioException);
Without cause chaining, debugging becomes much harder.
The type tells you what happened at the current abstraction level.
The cause tells you where it came from.
3. Practical Usage
Distinguish domain problems from infrastructure problems
Suppose a payment fails.
The exception strategy should distinguish between:
- invalid input from the caller
- business rejection like insufficient credit
- network timeout to a remote provider
- internal programming bug
These are not interchangeable categories.
They imply different handling and observability.
Typical uses of checked exceptions
Checked exceptions fit best when:
- the failure is external
- the caller may retry or fallback
- the failure is expected in normal operation
- the method boundary is low-level or infrastructure-oriented
Examples include file access, reflection lookups, and some legacy APIs.
Typical uses of unchecked exceptions
Unchecked exceptions fit best when:
- a precondition is violated
- an object is used incorrectly
- a bug is likely present
- forcing
throwseverywhere would add noise without helping recovery
This is why most modern framework APIs prefer unchecked exceptions for programming errors.
Common design question
Should every business failure be a checked exception?
Not necessarily.
Many teams model expected business outcomes as:
- return types
- result objects
- validation objects
- domain-specific unchecked exceptions at boundaries
The right choice depends on how exceptional the failure really is.
Logging and alerting impact
Exception type also affects operational handling.
For example:
IllegalArgumentExceptionfrom a public API may indicate bad client inputIllegalStateExceptionmay indicate an internal bug- repeated
IOExceptionmay indicate infrastructure instability OutOfMemoryErrorusually demands immediate operational investigation
This is where exception taxonomy becomes production engineering, not just syntax.
4. Code Examples
Example 1 — Checked exception
import java.io.IOException;
public class FileReaderService {
public String readConfig() throws IOException {
throw new IOException("Config file not found");
}
}
The caller must explicitly decide how to handle this failure.
Example 2 — Unchecked exception for invalid arguments
public class AgeValidator {
public void validate(int age) {
if (age < 0) {
throw new IllegalArgumentException("age must be non-negative");
}
}
}
This communicates a caller contract violation.
Example 3 — Illegal state
public class ReportExporter {
private boolean initialized;
public void initialize() {
initialized = true;
}
public void export() {
if (!initialized) {
throw new IllegalStateException("Exporter must be initialized first");
}
}
}
This signals misuse of object lifecycle rather than bad input value.
Example 4 — Preserve cause
import java.io.IOException;
public class ProfileService {
public void loadProfile() {
try {
throw new IOException("Disk read failed");
} catch (IOException exception) {
throw new IllegalStateException("Could not load profile", exception);
}
}
}
The abstraction changes, but the original cause remains available.
Example 5 — `Error` is different
public class ErrorExample {
public static void main(String[] args) {
throw new StackOverflowError("Demonstration only");
}
}
This is not how normal business errors should be modeled.
5. Trade-offs
| Aspect | Advantage | Cost / risk |
|---|---|---|
| Checked exceptions | Forces explicit handling | Can clutter signatures and call chains |
| Unchecked exceptions | Cleaner APIs | Easier to ignore if documentation is weak |
| Specific exception types | Better diagnostics and intent | Requires better design discipline |
| Broad exception types | Less initial effort | Loses precision and encourages bad handling |
| Preserving causes | Easier debugging | Slightly more code, but usually worth it |
The design tension is always the same.
Do you want stronger explicitness, or a lighter API surface?
Good design chooses based on caller responsibilities, not habit.
6. Common Mistakes
1. Throwing `Exception` everywhere
This destroys intent.
The code compiles, but the API no longer communicates what actually went wrong.
2. Using checked exceptions for programmer bugs
For example, invalid method arguments are usually better represented with unchecked exceptions such as IllegalArgumentException.
3. Swallowing exception causes
If you replace the exception type without preserving the cause, diagnosis becomes much harder.
4. Catching `Throwable`
This is almost always too broad.
It captures Error as well, which is usually not what you want in ordinary application logic.
5. Treating `Error` like business flow
OutOfMemoryError is not a validation result.
It is a system-level failure signal.
6. Using exception types inconsistently
If one part of the code uses IllegalArgumentException and another throws IllegalStateException for the same caller mistake, the API becomes confusing.
7. Deep Dive
Why Java kept checked exceptions
Checked exceptions are controversial.
Many developers love the explicitness.
Many others dislike the boilerplate.
Still, they express an important design idea:
some failures deserve first-class attention from the caller.
Whether you use them heavily or lightly, you should understand the intent behind them.
Exception types and architecture
At lower layers, infrastructure-specific checked exceptions can make sense.
At higher layers, applications often translate them into:
- domain exceptions
- service-layer exceptions
- HTTP responses
- error result objects
This is why exception types are part of architectural boundaries.
Interview framing
A strong interview answer does not stop at “checked exceptions must be declared.”
It usually adds:
- what kind of failure the type represents
- whether the caller can recover
- whether the type is part of API communication
- how the choice affects debugging and design
That extra layer is what makes the answer senior.
Precision over dogma
There is no perfect universal rule such as “checked is always better” or “unchecked is always modern.”
The better rule is:
choose the type that best communicates responsibility and likely handling.
Production impact
Exception type choices affect:
- metrics dashboards
- retry policies
- transaction rollbacks
- REST error mapping
- support investigations
Once you operate systems in production, bad exception taxonomy becomes very visible.
8. Interview Questions
What is the difference between `Error` and `Exception`?
Error usually represents serious system-level problems that applications do not normally recover from, while Exception represents conditions application code may handle or propagate.
What is the difference between checked and unchecked exceptions?
Checked exceptions must be caught or declared, while unchecked exceptions do not have to appear in method signatures and usually represent programmer mistakes or contract violations.
When would you use `IllegalArgumentException`?
When the caller passes an invalid value to a method and the failure indicates a violated precondition.
Why is `IllegalStateException` different?
It signals that the object or system is in the wrong state for the requested operation, even if the immediate method arguments are valid.
Why should you preserve the cause?
Because the higher-level exception explains the failure at the current abstraction, while the cause preserves the lower-level technical reason for debugging.
9. Glossary
| Term | Meaning |
|---|---|
Throwable |
Root type for everything that can be thrown |
Error |
Serious system-level failure type |
| checked exception | Exception that must be caught or declared |
| unchecked exception | RuntimeException subtype not enforced in signatures |
| cause | Original underlying throwable attached to another exception |
| contract violation | Caller misuse such as invalid input or invalid state |
| propagation | Letting the exception move to a higher layer |
| translation | Converting a low-level exception into a more suitable abstraction |
10. Cheatsheet
Throwablesplits mainly intoErrorandException.- Checked exceptions force explicit handling or declaration.
- Unchecked exceptions usually signal bugs, misuse, or violated contracts.
IllegalArgumentExceptionis about bad input.IllegalStateExceptionis about bad object/system state.Erroris usually not business-flow handling territory.- Specific exception types communicate intent better than broad ones.
- Preserve the cause when translating exceptions.
- Choose types based on caller responsibility and recovery options.
- In interviews, explain both semantics and design consequences.
🎮 Games
10 questions