Try-catch
The try...catch
block in Java is used to handle exceptions and prevents the abnormal termination of the program.
Here’s the syntax of a try...catch
block in Java.
try{
}
catch(exception) {
}
The try
block includes the code that might generate an exception.
The catch
block includes the code that is executed when there occurs an exception inside the try
block.
Example: Java try…catch block
class Main {
public static void main(String[] args) {
try {
int divideByZero = 5 / 0;
System.out.println("Rest of code in try block");
}
catch (ArithmeticException e) {
System.out.println("ArithmeticException => " + e.getMessage());
}
}
}
Output
ArithmeticException => / by zero
In the above example, notice the line,
int divideByZero = 5 / 0;
Here, we are trying to divide a number by zero. In this case, an exception occurs. Hence, we have enclosed this code inside the try
block.
When the program encounters this code, ArithmeticException
occurs. And, the exception is caught by the catch
block and executes the code inside the catch
block.
The catch
block is only executed if there exists an exception inside the try
block.
Note: In Java, we can use a try
block without a catch
block. However, we cannot use a catch
block without a try
block.
Java try…finally block
We can also use the try
block along with a finally block.
In this case, the finally block is always executed whether there is an exception inside the try block or not.
Example: Java try…finally block
class Main {
public static void main(String[] args) {
try {
int divideByZero = 5 / 0;
}
finally {
System.out.println("Finally block is always executed");
}
}
}
Output
Finally block is always executed
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:4)
In the above example, we have used the try
block along with the finally
block. We can see that the code inside the try
block is causing an exception.
However, the code inside the finally
block is executed irrespective of the exception.
Java try…catch…finally block
In Java, we can also use the finally block after the try...catch
block. For example,
import java.io.*;
class ListOfNumbers {
private int[] list = {5, 6, 8, 9, 2};
public void writeList() {
PrintWriter out = null;
try {
System.out.println("Entering try statement");
out = new PrintWriter(new FileWriter("OutputFile.txt"));
for (int i = 0; i < 7; i++) {
out.println("Value at: " + i + " = " + list[i]);
}
}
catch (Exception e) {
System.out.println("Exception => " + e.getMessage());
}
finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close();
}
else {
System.out.println("PrintWriter not open");
}
}
}
}
class Main {
public static void main(String[] args) {
ListOfNumbers list = new ListOfNumbers();
list.writeList();
}
}
Output
Entering try statement
Exception => Index 5 out of bounds for length 5
Closing PrintWriter
In the above example, we have created an array named list and a file named output.txt. Here, we are trying to read data from the array and storing to the file.
Notice the code,
for (int i = 0; i < 7; i++) {
out.println("Value at: " + i + " = " + list[i]);
}
Here, the size of the array is 5
and the last element of the array is at list[4]
. However, we are trying to access elements at a[5]
and a[6]
.
Hence, the code generates an exception that is caught by the catch block.
Since the finally
block is always executed, we have included code to close the PrintWriter
inside the finally block.
It is a good practice to use finally block to include important cleanup code like closing a file or connection.
Note: There are some cases when a finally
block does not execute:
- Use of
System.exit()
method - An exception occurs in the
finally
block - The death of a thread
Multiple Catch blocks
For each try
block, there can be zero or more catch
blocks. Multiple catch
blocks allow us to handle each exception differently.
The argument type of each catch
block indicates the type of exception that can be handled by it. For example,
class ListOfNumbers {
public int[] arr = new int[10];
public void writeList() {
try {
arr[10] = 11;
}
catch (NumberFormatException e1) {
System.out.println("NumberFormatException => " + e1.getMessage());
}
catch (IndexOutOfBoundsException e2) {
System.out.println("IndexOutOfBoundsException => " + e2.getMessage());
}
}
}
class Main {
public static void main(String[] args) {
ListOfNumbers list = new ListOfNumbers();
list.writeList();
}
}
Output
IndexOutOfBoundsException => Index 10 out of bounds for length 10
In this example, we have created an integer array named arr
of size 10.
Since the array index starts from 0, the last element of the array is at arr[9]
. Notice the statement,
arr[10] = 11;
Here, we are trying to assign a value to the index 10. Hence, IndexOutOfBoundException
occurs.
When an exception occurs in the try
block,
- The exception is thrown to the first
catch
block. The first catch
block does not handle an IndexOutOfBoundsException
, so it is passed to the next catch
block. - The second
catch
block in the above example is the appropriate exception handler because it handles an IndexOutOfBoundsException
. Hence, it is executed.
Catching Multiple Exceptions
From Java SE 7 and later, we can now catch more than one type of exception with one catch
block.
This reduces code duplication and increases code simplicity and efficiency.
Each exception type that can be handled by the catch
block is separated using a vertical bar |
.
Its syntax is:
try {
} catch (ExceptionType1 | Exceptiontype2 ex) {
}
To learn more, visit Java catching multiple exceptions.
Java try-with-resources statement
The try-with-resources statement is a try statement that has one or more resource declarations.
Its syntax is:
try (resource declaration) {
} catch (ExceptionType e1) {
}
The resource is an object to be closed at the end of the program. It must be declared and initialized in the try statement.
Let’s take an example.
try (PrintWriter out = new PrintWriter(new FileWriter("OutputFile.txt"))) {
}
The try-with-resources statement is also referred to as automatic resource management. This statement automatically closes all the resources at the end of the statement.
Finally
The finally block in java is used to put important codes such as clean up code e.g. closing the file or closing the connection. The finally block executes whether exception rise or not and whether exception handled or not. A finally contains all the crucial statements regardless of the exception occurs or not.
There are 3 possible cases where finally block can be used:
Case 1: When an exception does not rise
In this case, the program runs fine without throwing any exception and finally block execute after the try block.
import java.io.*;
class GFG {
public static void main(String[] args)
{
try {
System.out.println( "inside try block" );
System.out.println( 34 / 2 );
}
catch (ArithmeticException e) {
System.out.println( "Arithmetic Exception" );
}
finally {
System.out.println(
"finally : i execute always." );
}
}
}
|
Output
inside try block
17
finally : i execute always.
Case 2: When the exception rises and handled by the catch block
In this case, the program throws an exception but handled by the catch block, and finally block executes after the catch block.
import java.io.*;
class GFG {
public static void main(String[] args)
{
try {
System.out.println( "inside try block" );
System.out.println( 34 / 0 );
}
catch (ArithmeticException e) {
System.out.println(
"catch : exception handled." );
}
finally {
System.out.println( "finally : i execute always." );
}
}
}
|
Output
inside try block
catch : exception handled.
finally : i execute always.
Case 3: When exception rise and not handled by the catch block
In this case, the program throws an exception but not handled by catch so finally block execute after the try block and after the execution of finally block program terminate abnormally, But finally block execute fine.
import java.io.*;
class GFG {
public static void main(String[] args)
{
try {
System.out.println( "Inside try block" );
System.out.println( 34 / 0 );
}
catch (NullPointerException e) {
System.out.println(
"catch : exception not handled." );
}
finally {
System.out.println(
"finally : i will execute always." );
}
System.out.println( "i want to run" );
}
}
|
Output
Inside try block
finally : i will execute always.
Exception in thread "main" java.lang.ArithmeticException: / by zero
at GFG.main(File.java:10)
Throws and Throw
In Java, exceptions can be categorized into two types:
- Unchecked Exceptions: They are not checked at compile-time but at run-time.For example:
ArithmeticException
, NullPointerException
, ArrayIndexOutOfBoundsException
, exceptions under Error
class, etc. - Checked Exceptions: They are checked at compile-time. For example,
IOException
, InterruptedException
, etc.
Refer to Java Exceptions to learn in detail about checked and unchecked exceptions.
Usually, we don’t need to handle unchecked exceptions. It’s because unchecked exceptions occur due to programming errors. And, it is a good practice to correct them instead of handling them.
This tutorial will now focus on how to handle checked exceptions using throw
and throws
.
Java throws keyword
We use the throws
keyword in the method declaration to declare the type of exceptions that might occur within it.
Its syntax is:
accessModifier returnType methodName() throws ExceptionType1, ExceptionType2 … {
}
As you can see from the above syntax, we can use throws
to declare multiple exceptions.
Example 1: Java throws Keyword
import java.io.*;
class Main {
public static void findFile() throws IOException {
File newFile=new File("test.txt");
FileInputStream stream=new FileInputStream(newFile);
}
public static void main(String[] args) {
try{
findFile();
} catch(IOException e){
System.out.println(e);
}
}
}
Output
java.io.FileNotFoundException: test.txt (No such file or directory)
When we run this program, if the file test.txt
does not exist, FileInputStream
throws a FileNotFoundException
which extends the IOException
class.
If a method does not handle exceptions, the type of exceptions that may occur within it must be specified in the throws
clause so that methods further up in the call stack can handle them or specify them using throws
keyword themselves.
The findFile()
method specifies that an IOException
can be thrown. The main()
method calls this method and handles the exception if it is thrown.
Throwing multiple exceptions
Here’s how we can throw multiple exceptions using the throws
keyword.
import java.io.*;
class Main {
public static void findFile() throws NullPointerException, IOException, InvalidClassException {
… … …
… … …
… … …
}
public static void main(String[] args) {
try{
findFile();
} catch(IOException e1){
System.out.println(e1.getMessage());
} catch(InvalidClassException e2){
System.out.println(e2.getMessage());
}
}
}
Here, the findFile()
method specifies that it can throw NullPointerException
, IOException
, and InvalidClassException
in its throws
clause.
Note that we have not handled the NullPointerException
. This is because it is an unchecked exception. It is not necessary to specify it in the throws
clause and handle it.
throws keyword Vs. try…catch…finally
There might be several methods that can cause exceptions. Writing try...catch
for each method will be tedious and code becomes long and less-readable.
throws
is also useful when you have checked exception (an exception that must be handled) that you don’t want to catch in your current method.
Java throw keyword
The throw
keyword is used to explicitly throw a single exception.
When an exception is thrown, the flow of program execution transfers from the try
block to the catch
block. We use the throw
keyword within a method.
Its syntax is:
throw throwableObject;
A throwable object is an instance of class Throwable
or subclass of the Throwable
class.
Example 2: Java throw keyword
class Main {
public static void divideByZero() {
throw new ArithmeticException("Trying to divide by 0");
}
public static void main(String[] args) {
divideByZero();
}
}
Output
Exception in thread "main" java.lang.ArithmeticException: Trying to divide by 0
at Main.divideByZero(Main.java:3)
at Main.main(Main.java:7)
exit status 1
In this example, we are explicitly throwing an ArithmeticException.
Note: ArithmeticException
is an unchecked exception. It’s usually not necessary to handle unchecked exceptions.
Example 3: Throwing checked exception
import java.io.*;
class Main {
public static void findFile() throws IOException {
throw new IOException("File not found");
}
public static void main(String[] args) {
try {
findFile();
System.out.println("Rest of code in try block");
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
Output
File not found
The findFile()
method throws an IOException
with the message we passed to its constructor.
Note that since it is a checked exception, we must specify it in the throws
clause.
The methods that call this findFile()
method need to either handle this exception or specify it using throws
keyword themselves.
We have handled this exception in the main()
method. The flow of program execution transfers from the try
block to catch
block when an exception is thrown. So, the rest of the code in the try
block is skipped and statements in the catch
block are executed.
Custom Exceptions
The custom exception refers to the creation of your own exception to customize an exception according to the needs. The custom exceptions are derived from the Exception class.
Need of Java Custom Exceptions
- To categorize the exceptions based on the different types of errors in your project.
- To allow application-level exception handling.
Create a Custom Exception in Java
To create a custom exception, you need to create a class that must be inherited from the Exception class.
Syntax
Here is the syntax to create a custom class in Java –
class MyException extends Exception { }
You just need to extend the predefined Exception class to create your own Exception. These are considered to be checked exceptions.
Rules to Create Custom Exception
Keep the following points in mind when writing your own exception classes −
All exceptions must be a child of Throwable.
If you want to write a checked exception that is automatically enforced by the Handle or Declare Rule, you need to extend the Exception class.
If you want to write a runtime exception, you need to extend the RuntimeException class.
Java Custom Exception Example
The following InsufficientFundsException class is a user-defined exception that extends the Exception class, making it a checked exception. An exception class is like any other class, containing useful fields and methods.
class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } }
To demonstrate using our user-defined exception, the following CheckingAccount class contains a withdraw() method that throws an InsufficientFundsException.
class CheckingAccount { private double balance; private int number; public CheckingAccount(int number) { this.number = number; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) throws InsufficientFundsException { if(amount <= balance) { balance -= amount; }else { double needs = amount – balance; throw new InsufficientFundsException(needs); } } public double getBalance() { return balance; } public int getNumber() { return number; } }
The following BankDemo program demonstrates invoking the deposit() and withdraw() methods of CheckingAccount.
package com.tutorialspoint; public class BankDemo { public static void main(String [] args) { CheckingAccount c = new CheckingAccount(101); System.out.println(“Depositing $500…”); c.deposit(500.00); try { System.out.println(“\nWithdrawing $100…”); c.withdraw(100.00); System.out.println(“\nWithdrawing $600…”); c.withdraw(600.00); } catch (InsufficientFundsException e) { System.out.println(“Sorry, but you are short $” + e.getAmount()); e.printStackTrace(); } } } class CheckingAccount { private double balance; private int number; public CheckingAccount(int number) { this.number = number; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) throws InsufficientFundsException { if(amount <= balance) { balance -= amount; }else { double needs = amount – balance; throw new InsufficientFundsException(needs); } } public double getBalance() { return balance; } public int getNumber() { return number; } } class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } }
Output
Compile all the above three files and run BankDemo. This will produce the following result −
Depositing $500...
Withdrawing $100...
Withdrawing $600...
Sorry, but you are short $200.0
com.tutorialspoint.InsufficientFundsException
at com.tutorialspoint.CheckingAccount.withdraw(BankDemo.java:39)
at com.tutorialspoint.BankDemo.main(BankDemo.java:14)
In next example, we’re declaring our custom exception as RuntimeException to make it as unchecked exception class as below −
class MyException extends RuntimeException { }
Example to Create Custom Class by Extending Runtime Exception
We are extending the predefined RuntimeException class to create your own Exception as an unchecked exception. The following InsufficientFundsException class is a user-defined exception that extends the RuntimeException class, making it a unchecked exception. An RuntimeException class is like any other class, containing useful fields and methods.
class InsufficientFundsException extends RuntimeException { private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } }
The following BankDemo program demonstrates invoking the deposit() and withdraw() methods of CheckingAccount using unchecked exception.
package com.tutorialspoint; public class BankDemo { public static void main(String [] args) { CheckingAccount c = new CheckingAccount(101); System.out.println(“Depositing $500…”); c.deposit(500.00); System.out.println(“\nWithdrawing $100…”); c.withdraw(100.00); System.out.println(“\nWithdrawing $600…”); c.withdraw(600.00); } } class CheckingAccount { private double balance; private int number; public CheckingAccount(int number) { this.number = number; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) { if(amount <= balance) { balance -= amount; }else { double needs = amount – balance; throw new InsufficientFundsException(needs); } } public double getBalance() { return balance; } public int getNumber() { return number; } } class InsufficientFundsException extends RuntimeException { private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } }
Output
Compile and run BankDemo. This will produce the following result −
Depositing $500...
Withdrawing $100...
Withdrawing $600...
Exception in thread "main"
com.tutorialspoint.InsufficientFundsException
at com.tutorialspoint.CheckingAccount.withdraw(BankDemo.java:35)
at com.tutorialspoint.BankDemo.main(BankDemo.java:13)