Skip to content

Commit 2cc698b

Browse files
feat: add MCQ quiz and banking transaction system with custom exception handling
1 parent 2459e6d commit 2cc698b

File tree

3 files changed

+1107
-0
lines changed

3 files changed

+1107
-0
lines changed

module03-exceptions/answers.md

Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
# Module 03: Exception Handling - Answers
2+
3+
## MCQ Quiz Answers
4+
5+
### 1. Which is the correct exception hierarchy in Java?
6+
**Answer: b) Throwable → Exception → RuntimeException**
7+
*Explanation: Throwable is the root, Exception extends Throwable, RuntimeException extends Exception.*
8+
9+
### 2. What happens if you don't handle a checked exception?
10+
**Answer: b) Compilation error**
11+
*Explanation: Checked exceptions must be either caught or declared in the method signature using throws.*
12+
13+
### 3. Which is the best practice for exception handling?
14+
**Answer: c) Catch specific exceptions rather than general ones**
15+
*Explanation: Catching specific exceptions allows for more precise error handling and better debugging.*
16+
17+
### 4. What is the purpose of the finally block?
18+
**Answer: c) Execute code regardless of whether an exception occurs**
19+
*Explanation: Finally block always executes (except in case of System.exit() or JVM crash).*
20+
21+
### 5. When should you create custom exceptions?
22+
**Answer: b) When you need to provide specific error information**
23+
*Explanation: Custom exceptions should add value by providing specific context or behavior.*
24+
25+
### 6. What is the difference between throw and throws?
26+
**Answer: c) throw is used to actually throw an exception, throws declares exceptions**
27+
*Explanation: throw keyword throws an exception, throws keyword declares what exceptions a method might throw.*
28+
29+
### 7. Which statement about try-with-resources is correct?
30+
**Answer: c) Automatically closes resources that implement AutoCloseable**
31+
*Explanation: Try-with-resources automatically calls close() on resources implementing AutoCloseable.*
32+
33+
### 8. What happens when an exception is thrown in a finally block?
34+
**Answer: b) It suppresses the original exception**
35+
*Explanation: If finally block throws an exception, it can suppress the original exception unless properly handled.*
36+
37+
### 9. Which type of exception should you typically NOT catch?
38+
**Answer: d) OutOfMemoryError**
39+
*Explanation: Errors indicate serious problems that applications shouldn't try to catch.*
40+
41+
### 10. What is exception chaining?
42+
**Answer: a) Wrapping one exception inside another**
43+
*Explanation: Exception chaining preserves the original exception as the cause of a new exception.*
44+
45+
---
46+
47+
## File Reader Task Solution
48+
49+
```java
50+
import java.io.*;
51+
import java.nio.file.*;
52+
import java.util.*;
53+
import java.util.logging.Logger;
54+
import java.util.logging.Level;
55+
56+
// Custom exceptions
57+
class FileReadException extends Exception {
58+
public FileReadException(String message, Throwable cause) {
59+
super(message, cause);
60+
}
61+
}
62+
63+
class InvalidFileFormatException extends FileReadException {
64+
public InvalidFileFormatException(String message) {
65+
super(message, null);
66+
}
67+
}
68+
69+
// Main FileReader class
70+
public class SafeFileReader {
71+
private static final Logger logger = Logger.getLogger(SafeFileReader.class.getName());
72+
73+
// Read file with comprehensive error handling
74+
public List<String> readFile(String filePath) throws FileReadException {
75+
// Validate input
76+
if (filePath == null || filePath.trim().isEmpty()) {
77+
throw new IllegalArgumentException("File path cannot be null or empty");
78+
}
79+
80+
Path path = Paths.get(filePath);
81+
List<String> lines = new ArrayList<>();
82+
83+
// Check if file exists and is readable
84+
if (!Files.exists(path)) {
85+
throw new FileReadException("File does not exist: " + filePath, null);
86+
}
87+
88+
if (!Files.isReadable(path)) {
89+
throw new FileReadException("File is not readable: " + filePath, null);
90+
}
91+
92+
// Try-with-resources for automatic resource management
93+
try (BufferedReader reader = Files.newBufferedReader(path)) {
94+
String line;
95+
int lineNumber = 0;
96+
97+
while ((line = reader.readLine()) != null) {
98+
lineNumber++;
99+
100+
// Basic validation - skip empty lines
101+
if (!line.trim().isEmpty()) {
102+
lines.add(line);
103+
}
104+
}
105+
106+
logger.info("Successfully read " + lines.size() + " lines from " + filePath);
107+
return lines;
108+
109+
} catch (IOException e) {
110+
String errorMsg = "Failed to read file: " + filePath;
111+
logger.log(Level.SEVERE, errorMsg, e);
112+
throw new FileReadException(errorMsg, e);
113+
}
114+
}
115+
116+
// Read CSV file with validation
117+
public List<String[]> readCSVFile(String filePath) throws FileReadException, InvalidFileFormatException {
118+
// First read the file
119+
List<String> lines = readFile(filePath);
120+
List<String[]> csvData = new ArrayList<>();
121+
122+
if (lines.isEmpty()) {
123+
throw new InvalidFileFormatException("CSV file is empty");
124+
}
125+
126+
// Parse CSV data
127+
int expectedColumns = -1;
128+
int lineNumber = 0;
129+
130+
try {
131+
for (String line : lines) {
132+
lineNumber++;
133+
String[] columns = line.split(",");
134+
135+
// Remove leading/trailing whitespace
136+
for (int i = 0; i < columns.length; i++) {
137+
columns[i] = columns[i].trim();
138+
}
139+
140+
// Validate column count consistency
141+
if (expectedColumns == -1) {
142+
expectedColumns = columns.length;
143+
} else if (columns.length != expectedColumns) {
144+
throw new InvalidFileFormatException(
145+
String.format("Inconsistent column count at line %d. Expected %d, found %d",
146+
lineNumber, expectedColumns, columns.length));
147+
}
148+
149+
csvData.add(columns);
150+
}
151+
152+
logger.info("Successfully parsed " + csvData.size() + " CSV rows");
153+
return csvData;
154+
155+
} catch (Exception e) {
156+
if (e instanceof InvalidFileFormatException) {
157+
throw e; // Re-throw our custom exception
158+
}
159+
throw new FileReadException("Error parsing CSV at line " + lineNumber, e);
160+
}
161+
}
162+
163+
// Safe file reading with retry mechanism
164+
public List<String> readFileWithRetry(String filePath, int maxRetries) throws FileReadException {
165+
FileReadException lastException = null;
166+
167+
for (int attempt = 1; attempt <= maxRetries; attempt++) {
168+
try {
169+
return readFile(filePath);
170+
171+
} catch (FileReadException e) {
172+
lastException = e;
173+
logger.warning("Attempt " + attempt + " failed: " + e.getMessage());
174+
175+
if (attempt < maxRetries) {
176+
try {
177+
// Wait before retry (exponential backoff)
178+
Thread.sleep(1000 * attempt);
179+
} catch (InterruptedException ie) {
180+
Thread.currentThread().interrupt();
181+
throw new FileReadException("Interrupted during retry", ie);
182+
}
183+
}
184+
}
185+
}
186+
187+
throw new FileReadException("Failed after " + maxRetries + " attempts", lastException);
188+
}
189+
190+
// Method that handles multiple file types
191+
public Object readFileByType(String filePath) throws FileReadException {
192+
String extension = getFileExtension(filePath);
193+
194+
try {
195+
switch (extension.toLowerCase()) {
196+
case "txt":
197+
return readFile(filePath);
198+
case "csv":
199+
return readCSVFile(filePath);
200+
default:
201+
throw new InvalidFileFormatException("Unsupported file type: " + extension);
202+
}
203+
} catch (InvalidFileFormatException e) {
204+
throw new FileReadException("Invalid file format", e);
205+
}
206+
}
207+
208+
// Helper method to get file extension
209+
private String getFileExtension(String filePath) {
210+
int lastDotIndex = filePath.lastIndexOf('.');
211+
if (lastDotIndex == -1) {
212+
return "";
213+
}
214+
return filePath.substring(lastDotIndex + 1);
215+
}
216+
217+
// Cleanup method for resource management
218+
public void cleanup() {
219+
// Any cleanup operations if needed
220+
logger.info("FileReader cleanup completed");
221+
}
222+
}
223+
224+
// Test class demonstrating exception handling
225+
public class FileReaderTest {
226+
public static void main(String[] args) {
227+
SafeFileReader reader = new SafeFileReader();
228+
229+
// Test 1: Reading a normal file
230+
try {
231+
System.out.println("=== Test 1: Reading normal file ===");
232+
List<String> lines = reader.readFile("test.txt");
233+
System.out.println("Read " + lines.size() + " lines");
234+
235+
} catch (FileReadException e) {
236+
System.err.println("Error reading file: " + e.getMessage());
237+
if (e.getCause() != null) {
238+
System.err.println("Cause: " + e.getCause().getMessage());
239+
}
240+
} catch (IllegalArgumentException e) {
241+
System.err.println("Invalid argument: " + e.getMessage());
242+
}
243+
244+
// Test 2: Reading non-existent file
245+
try {
246+
System.out.println("\n=== Test 2: Reading non-existent file ===");
247+
reader.readFile("nonexistent.txt");
248+
249+
} catch (FileReadException e) {
250+
System.err.println("Expected error: " + e.getMessage());
251+
}
252+
253+
// Test 3: Reading CSV file
254+
try {
255+
System.out.println("\n=== Test 3: Reading CSV file ===");
256+
List<String[]> csvData = reader.readCSVFile("data.csv");
257+
System.out.println("Read " + csvData.size() + " CSV rows");
258+
259+
// Display first row if available
260+
if (!csvData.isEmpty()) {
261+
System.out.println("First row: " + Arrays.toString(csvData.get(0)));
262+
}
263+
264+
} catch (FileReadException | InvalidFileFormatException e) {
265+
System.err.println("CSV Error: " + e.getMessage());
266+
}
267+
268+
// Test 4: Reading with retry
269+
try {
270+
System.out.println("\n=== Test 4: Reading with retry ===");
271+
List<String> lines = reader.readFileWithRetry("test.txt", 3);
272+
System.out.println("Successfully read with retry: " + lines.size() + " lines");
273+
274+
} catch (FileReadException e) {
275+
System.err.println("Failed even with retry: " + e.getMessage());
276+
}
277+
278+
// Test 5: Reading by file type
279+
try {
280+
System.out.println("\n=== Test 5: Reading by file type ===");
281+
Object result = reader.readFileByType("data.csv");
282+
283+
if (result instanceof List) {
284+
@SuppressWarnings("unchecked")
285+
List<String[]> csvResult = (List<String[]>) result;
286+
System.out.println("Auto-detected CSV: " + csvResult.size() + " rows");
287+
}
288+
289+
} catch (FileReadException e) {
290+
System.err.println("Type-based reading error: " + e.getMessage());
291+
}
292+
293+
// Test 6: Exception chaining example
294+
try {
295+
System.out.println("\n=== Test 6: Exception chaining ===");
296+
throw new FileReadException("High-level error",
297+
new IOException("Low-level IO error"));
298+
299+
} catch (FileReadException e) {
300+
System.err.println("Main exception: " + e.getMessage());
301+
System.err.println("Root cause: " + e.getCause().getMessage());
302+
303+
// Print full stack trace for debugging
304+
e.printStackTrace();
305+
}
306+
307+
// Cleanup
308+
finally {
309+
reader.cleanup();
310+
}
311+
}
312+
}
313+
314+
// Utility class for creating test files
315+
public class TestFileCreator {
316+
public static void createTestFiles() {
317+
// Create a simple text file
318+
try (PrintWriter writer = new PrintWriter("test.txt")) {
319+
writer.println("Line 1: Hello World");
320+
writer.println("Line 2: Java Exception Handling");
321+
writer.println("Line 3: Try-catch-finally blocks");
322+
writer.println(""); // Empty line (will be skipped)
323+
writer.println("Line 4: Custom exceptions");
324+
} catch (IOException e) {
325+
System.err.println("Failed to create test.txt: " + e.getMessage());
326+
}
327+
328+
// Create a CSV file
329+
try (PrintWriter writer = new PrintWriter("data.csv")) {
330+
writer.println("Name, Age, City");
331+
writer.println("Alice, 25, New York");
332+
writer.println("Bob, 30, London");
333+
writer.println("Charlie, 35, Tokyo");
334+
} catch (IOException e) {
335+
System.err.println("Failed to create data.csv: " + e.getMessage());
336+
}
337+
338+
System.out.println("Test files created successfully");
339+
}
340+
341+
public static void main(String[] args) {
342+
createTestFiles();
343+
}
344+
}
345+
```
346+
347+
## Key Exception Handling Concepts Demonstrated:
348+
349+
1. **Custom Exceptions**: Created `FileReadException` and `InvalidFileFormatException`
350+
2. **Exception Chaining**: Using `cause` parameter to preserve original exceptions
351+
3. **Try-with-Resources**: Automatic resource management with `BufferedReader`
352+
4. **Multiple Catch Blocks**: Handling different exception types appropriately
353+
5. **Finally Block**: Cleanup operations that always execute
354+
6. **Input Validation**: Checking parameters before processing
355+
7. **Logging**: Using Java's built-in logging for error tracking
356+
8. **Retry Mechanism**: Implementing exponential backoff for transient failures
357+
9. **Resource Management**: Proper cleanup of system resources
358+
10. **Exception Documentation**: Clear error messages with context
359+
360+
This solution demonstrates production-ready exception handling patterns that provide robustness, debugging information, and graceful error recovery.

0 commit comments

Comments
 (0)