Flashcards for topic Exceptions
What's wrong with the following loop pattern and why should it be avoided?
try { int i = 0; while(true) range[i++].climb(); } catch (ArrayIndexOutOfBoundsException e) { }
This code abuses exceptions for ordinary control flow - a serious anti-pattern because:
The proper alternative is a standard loop:
for (Mountain m : range) m.climb();
Exceptions should only be used for exceptional conditions, not regular control flow.
What are the three types of throwables in Java, and how should you decide which one to implement when creating your own exception classes?
The three types of throwables are:
Exception
but not RuntimeException
)
RuntimeException
)
Error
)
When implementing custom exceptions:
RuntimeException
Error
subclassesNote: With rare exceptions like AssertionError
, you shouldn't throw Error
s either.
What is the "cardinal rule" for deciding between checked and unchecked exceptions, and what factors should influence this decision?
Cardinal rule: Use checked exceptions for conditions from which the caller can reasonably be expected to recover.
Decision factors:
Use checked exceptions when:
Use runtime exceptions when:
If it's unclear whether recovery is possible, favor unchecked exceptions.
Remember: Checked exceptions increase API complexity but enhance reliability when used appropriately.
Explain why overuse of checked exceptions in APIs can be problematic and describe two techniques to convert a checked exception into a more API-friendly alternative.
Problems with overusing checked exceptions:
Two conversion techniques:
// Instead of: public FileData readFile(File f) throws IOException { /*...*/ } // Consider: public Optional<FileData> readFile(File f) { try { // Read file return Optional.of(fileData); } catch (IOException e) { return Optional.empty(); } }
// Instead of one method throwing checked exception: public void action(Args args) throws CheckedException { /*...*/ } // Create two methods: public boolean actionPermitted(Args args) { /*...*/ } public void action(Args args) { // throws unchecked exception if needed if (!actionPermitted(args)) { throw new UncheckedExceptionVariant(); } // Perform action }
The second approach is inappropriate for concurrent access without synchronization.
What is exception translation and when should it be used?
Exception translation is when higher layers catch lower-level exceptions and throw exceptions that can be explained in terms of the higher-level abstraction.
Use it when:
Code pattern:
// Exception Translation try { // Use lower-level abstraction to do our bidding } catch (LowerLevelException e) { throw new HigherLevelException(...); }
This prevents breaking client code if implementation changes and maintains abstraction integrity.
Explain exception chaining with its implementation and benefits.
Exception chaining is a special form of exception translation where the lower-level exception is preserved as the "cause" of the higher-level exception.
Implementation:
// Exception Chaining try { // Use lower-level abstraction to do our bidding } catch (LowerLevelException cause) { throw new HigherLevelException(cause); } // Creating a chaining-aware exception class class HigherLevelException extends Exception { HigherLevelException(Throwable cause) { super(cause); } }
Benefits:
How should detail messages in custom exceptions be designed for maximum diagnostic value?
For maximum diagnostic value, exception detail messages should:
Contain values of all parameters and fields that contributed to the exception
Avoid including security-sensitive information
Focus on information content over prose readability
Centralize detail message generation in constructors
Example implementation:
public IndexOutOfBoundsException(int lowerBound, int upperBound, int index) { // Generate a detail message that captures the failure super(String.format("Lower bound: %d, Upper bound: %d, Index: %d", lowerBound, upperBound, index)); // Save failure information for programmatic access this.lowerBound = lowerBound; this.upperBound = upperBound; this.index = index; }
Remember: The stack trace may be the ONLY information available when diagnosing production issues.
What are the best practices for documenting exceptions in Java APIs?
Best practices for documenting exceptions:
Document all exceptions, both checked and unchecked
Declare each checked exception individually in the throws clause
Document precisely when each exception is thrown
For interface methods, document unchecked exceptions thoroughly
For multiple methods throwing the same exception for the same reason:
Distinguish between checked and unchecked exceptions in documentation
Remember: Undocumented exceptions make it difficult or impossible for others to effectively use your classes and interfaces.
What are the critical do's and don'ts regarding exception handling in order to avoid leaking implementation details through APIs?
Critical do's and don'ts to avoid leaking implementation details:
DO:
DON'T:
Example of implementation leakage:
// BAD: Leaks implementation details public void saveUser(User user) throws SQLException { // Leaks database implementation // database operations... } // GOOD: Maintains abstraction public void saveUser(User user) throws UserStorageException { try { // database operations... } catch (SQLException e) { throw new UserStorageException("Failed to store user", e); } }
This approach preserves implementation flexibility while providing meaningful exceptions.
What are the tradeoffs of implementing the recovery code approach to failure atomicity?
Recovery Code Approach Tradeoffs:
Advantages:
Disadvantages:
This approach is generally reserved for persistent data structures where durability is critical, such as databases and file systems.
Showing 10 of 34 cards. Add this deck to your collection to see all cards.