Exception Handling is a mechanism designed to manage runtime errors and maintain normal application control flow. An exception represents an unexpected runtime event (e.g., division by zero, missing file, array index out of bounds) that disrupts execution if left uncaught.
The basic construct places risky code inside a try block and handles errors
inside one or more catch (or except) blocks.
public class Main {
public static void main(String[] args) {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[5]); // ArrayIndexOutOfBoundsException
int result = 10 / 0; // ArithmeticException
}
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Error: Array index out of bounds!");
}
catch (ArithmeticException e) {
System.out.println("Error: Division by zero!");
}
System.out.println("Program continues...");
}
}
#include <iostream>
#include <vector>
#include <stdexcept>
using namespace std;
int main() {
try {
vector<int> arr = {1, 2, 3};
cout << arr.at(5) << "\n"; // Throws std::out_of_range
int result = 10 / 0;
}
catch (const out_of_range& e) {
cout << "Error: Index out of range!\n";
}
catch (const exception& e) {
cout << "Error: " << e.what() << "\n";
}
cout << "Program continues...\n";
return 0;
}
def main():
try:
arr = [1, 2, 3]
print(arr[5]) # IndexError
result = 10 / 0 # ZeroDivisionError
except IndexError:
print("Error: List index out of range!")
except ZeroDivisionError:
print("Error: Division by zero!")
print("Program continues...")
if __name__ == "__main__":
main()
finally vs RAIIWhen an exception occurs, allocated resources must be freed to avoid leaks.
finally block (or Python
with context managers) that executes regardless of whether an exception is
thrown.
finally keyword. Instead, C++ relies on
RAII (Resource Acquisition Is Initialization) where object destructors run
automatically during stack unwinding when scope is exited.
public class Main {
public static void main(String[] args) {
try {
int result = 10 / 2;
System.out.println("Result: " + result);
}
catch (Exception e) {
System.out.println("An error occurred.");
}
finally {
// Always executes regardless of exceptions
System.out.println("Finally block executed (Cleanup).");
}
System.out.println("Program continues...");
}
}
#include <iostream>
#include <stdexcept>
using namespace std;
struct Cleanup {
~Cleanup() {
// RAII destructor runs automatically on stack unwinding
cout << "Cleanup executed (RAII Destructor).\n";
}
};
int main() {
Cleanup c; // Guard object
try {
cout << "Inside try block.\n";
throw runtime_error("Something went wrong!");
}
catch (const exception& e) {
cout << "Caught: " << e.what() << "\n";
}
cout << "Program continues...\n";
return 0;
}
def main():
try:
result = 10 / 2
print("Result:", result)
except Exception as e:
print("An error occurred.")
finally:
# Always executes regardless of exceptions
print("Finally block executed (Cleanup).")
print("Program continues...")
if __name__ == "__main__":
main()
Languages provide keywords to manually trigger exceptions or declare potential exceptions in method signatures.
throw (Java / C++) & raise (Python):
Explicitly throws an exception object.
throws (Java): Declared in method signatures to force callers
to catch or handle checked exceptions.
noexcept to promise a function never throws.
class Demo {
// throws declares checked exceptions callers must handle
static void divide() throws ArithmeticException {
throw new ArithmeticException("Division by zero!"); // throw keyword
}
public static void main(String[] args) {
try {
divide();
}
catch (ArithmeticException e) {
System.out.println("Handled: " + e.getMessage());
}
}
}
#include <iostream>
#include <stdexcept>
using namespace std;
void divide() {
// throw keyword raises runtime error
throw runtime_error("Division by zero!");
}
int main() {
try {
divide(); // Exception propagates to main caller
}
catch (const exception& e) {
cout << "Handled: " << e.what() << "\n";
}
return 0;
}
def divide():
# raise keyword triggers exception
raise ZeroDivisionError("Division by zero!")
def main():
try:
divide() # Exception propagates to caller
except ZeroDivisionError as e:
print("Handled:", str(e))
if __name__ == "__main__":
main()
Custom exception classes allow developers to model domain-specific error conditions.
class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
public class Main {
public static void main(String[] args) {
try {
throw new CustomException("Application error occurred!");
}
catch (CustomException e) {
System.out.println("Caught: " + e.getMessage());
}
}
}
#include <iostream>
#include <exception>
using namespace std;
class CustomException : public exception {
public:
const char* what() const noexcept override {
return "Application error occurred!";
}
};
int main() {
try {
throw CustomException();
}
catch (const CustomException& e) {
cout << "Caught: " << e.what() << "\n";
}
return 0;
}
class CustomException(Exception):
def __init__(self, message):
super().__init__(message)
def main():
try:
raise CustomException("Application error occurred!")
except CustomException as e:
print("Caught:", str(e))
if __name__ == "__main__":
main()
Java makes a fundamental distinction between Checked Exceptions (enforced by
the compiler at build time, e.g. IOException) and
Unchecked Exceptions (runtime errors inheriting from
RuntimeException).
In contrast, C++ and Python have NO checked exceptions. All exceptions in C++ and Python are unchecked and propagate freely at runtime unless explicitly caught by a caller.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try {
File file = new File("nonexistent.txt");
Scanner reader = new Scanner(file); // Throws FileNotFoundException
}
catch (FileNotFoundException e) {
System.out.println("Error: File not found!");
}
}
}
#include <iostream>
#include <fstream>
using namespace std;
int main() {
try {
ifstream file("nonexistent.txt");
file.exceptions(ifstream::failbit | ifstream::badbit);
string line;
getline(file, line);
}
catch (const ios_base::failure& e) {
cout << "Error: File not found or unreadable!\n";
}
return 0;
}
def main():
try:
with open("nonexistent.txt", "r") as f:
data = f.read()
except FileNotFoundError:
print("Error: File not found!")
if __name__ == "__main__":
main()
| Feature | Java | C++ | Python |
|---|---|---|---|
| Trigger Keyword | throw new Exception() |
throw Exception() |
raise Exception() |
| Signature Declaration | throws ExceptionType |
No throws; use noexcept for non-throwing |
No declaration required (docstrings used) |
| Resource Cleanup | finally block / try-with-resources |
RAII (destructors auto-run on stack unwind) | finally block / with context managers |
| Checked Exceptions | Yes (e.g. IOException) |
No (all exceptions are unchecked) | No (all exceptions are unchecked) |
How does C++ achieve automatic resource cleanup during exceptions without a
finally block?
Which language feature requires callers to catch or declare exceptions at compile time?
Definition ⇒ Intercept runtime errors to prevent program crashes and preserve control flow
Flow ⇒ try (risky code) — catch/except (handler) —
finally/RAII (cleanup)
Java / Python ⇒ finally block executes regardless of exceptions ; Python uses
with context managers
C++ ⇒ No finally ; uses RAII (destructors auto-called during stack unwinding)
Throwing ⇒ Java/C++ throw ; Python raise
Signatures ⇒ Java throws forces caller handling ; C++ uses optional
noexcept ; Python relies on propagation
Catching Rule ⇒ Catch by const reference in C++ to prevent object slicing
Java ⇒ Checked (compile-time enforced, eg IOException) vs Unchecked
(RuntimeException)
C++ & Python ⇒ No checked exceptions ; all exceptions are unchecked
Primary source: Oracle Java Tutorials — Exceptions, cppreference — Exceptions & Python Docs — Errors and Exceptions. Ask me anything that's unclear.
Questions? Ask your agent — you can follow up on any concept, quiz answer, or how this applies to a specific coding problem. Review the Java glossary or syntax quick reference for a compressed overview.