The try-catch statement in Java is used to handle exceptions. The try block contains code that may cause an exception, while the catch block handles a matching exception.
Without exception handling, an uncaught exception can terminate the current thread. A try-catch statement lets a program respond to certain exceptions and continue where appropriate.
class Main {
public static void main(String[] args) {
try {
int result = 10 / 0;
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero");
}
System.out.println("Program continues");
}
}
Cannot divide by zero
Program continues
try {
// Code that may throw an exception
} catch (ExceptionType e) {
// Handle the exception
}
Important points:
ArithmeticException is an unchecked exception. Integer division by zero is a common cause.
class Main {
public static void main(String[] args) {
int a = 20;
int b = 0;
try {
System.out.println(a / b);
} catch (ArithmeticException e) {
System.out.println("Invalid division");
}
}
}
Invalid division
The catch block handles the exception instead of allowing it to remain uncaught.
This exception occurs when code accesses an array using an invalid index.
class Main {
public static void main(String[] args) {
int[] numbers = {10, 20, 30};
try {
System.out.println(numbers[5]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid array index");
}
}
}
Invalid array index
The valid indexes for this array are 0, 1, and 2.
A NullPointerException can occur when code tries to use an object reference that is null.
class Main {
public static void main(String[] args) {
String name = null;
try {
System.out.println(name.length());
} catch (NullPointerException e) {
System.out.println("Name is not initialized");
}
}
}
Name is not initialized
In real applications, it is usually better to prevent unexpected null values where possible, rather than relying only on exception handling.
Multiple catch blocks can handle different exception types from the same try block.
class Main {
public static void main(String[] args) {
try {
int[] numbers = {10, 20, 30};
System.out.println(numbers[5]);
} catch (ArithmeticException e) {
System.out.println("Arithmetic error");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Array index error");
} catch (Exception e) {
System.out.println("Other error");
}
}
}
Array index error
The exception object provides methods such as
getMessage() to retrieve its message.
class Main {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
}
}
The message describes the exception. Its exact wording can depend on the Java runtime, so do not rely on a particular message for program logic.
You can also print the exception type:
System.out.println(e.getClass().getSimpleName());
For this example, the exception type is:
ArithmeticException
Scanner's nextInt() can throw
InputMismatchException if the entered value
is not an integer.
import java.util.Scanner;
import java.util.InputMismatchException;
class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
try {
System.out.print("Enter an integer: ");
int number = sc.nextInt();
System.out.println("Number: " + number);
} catch (InputMismatchException e) {
System.out.println("Please enter a valid integer");
} finally {
sc.close();
}
}
}
Enter an integer: hello
Please enter a valid integer
The finally block closes the Scanner whether the input is valid or an exception is handled. This example ends after handling invalid input.
A try-catch statement can be placed inside another try block. This is called nested try-catch.
class Main {
public static void main(String[] args) {
try {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Division error");
}
int[] numbers = {10, 20};
System.out.println(numbers[5]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Array index error");
}
}
}
Division error
Array index error
The inner catch handles the division exception. The outer catch handles the array index exception.
The finally block is commonly used for cleanup operations and generally runs whether or not an exception is thrown.
class Main {
public static void main(String[] args) {
try {
int result = 10 / 0;
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero");
} finally {
System.out.println("Execution finished");
}
}
}
Cannot divide by zero
Execution finished
In production code, try-with-resources is often preferred for automatically closing files, streams, and other AutoCloseable resources.
You can place exception handling inside a method to manage errors close to the operation that causes them.
class Calculator {
void divide(int a, int b) {
try {
int result = a / b;
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero");
}
}
}
class Main {
public static void main(String[] args) {
Calculator c1 = new Calculator();
c1.divide(20, 5);
c1.divide(20, 0);
}
}
Result: 4
Cannot divide by zero
Each call handles its own division error, allowing the second call to execute.
class Main {
public static void main(String[] args) {
int a = 20;
int b = 0;
if (b != 0) {
System.out.println(a / b);
} else {
System.out.println("Divisor must not be zero");
}
}
}
Divisor must not be zero
When the condition is expected and easy to check, validating it directly can be clearer than deliberately triggering an exception.
1. Which block handles a matching exception?
2. Which exception commonly occurs when dividing an integer by zero?
3. Which block is commonly used for cleanup?