[!NOTE] Even if your code compiles perfectly, real-world problems will occur while the program is actually running. A user might try to upload a corrupted file, the database server might catch fire, or the network might partition.
When Java encounters a fatal error during runtime, it throws an Exception. If you do not explicitly catch and handle that exception, your entire application will instantly crash.
The Try-Catch Block
The try-catch block allows you to anticipate potential failures and provide a safe fallback mechanism instead of a hard crash.
public class InputExample {
public static void main(String[] args) {
try {
// 1. The DANGEROUS code goes in the 'try' block
int[] myNumbers = {1, 2, 3};
// FATAL ERROR! Index 10 does not exist!
System.out.println(myNumbers[10]);
// This line is NEVER reached because the error immediately jumps to 'catch'
System.out.println("Execution continues...");
} catch (Exception e) {
// 2. The FALLBACK code goes in the 'catch' block
System.out.println("Something went wrong, but the app survived!");
System.out.println("Developer Error Log: " + e.getMessage());
}
}
}
The 'finally' Block
Often, you open an expensive system resource (like a database connection or a file stream) in your try block. If an error occurs halfway through, the code jumps to catch, and your command to close that connection is bypassed!
The finally block executes no matter what happens. Even if a try block successfully returns, or a catch block catches an error, the finally block is guaranteed to execute before the method finishes.
Scanner scan = new Scanner(System.in);
try {
int age = scan.nextInt();
System.out.println("Valid age: " + age);
} catch (Exception e) {
System.out.println("Please enter a valid number!");
} finally {
// This code will always execute! Prevents memory leaks!
scan.close();
System.out.println("Scanner closed successfully.");
}
[!TIP] Catching Specific Errors: Instead of catching a generic
Exception e, you should catch specific exceptions likeNullPointerExceptionorFileNotFoundException. This allows you to write custom fallback logic depending on exactly why the code failed.