Try catch in Java


JavaViews 1337

Java exception occurs when it executes an unexpected condition in the code. We can handle this exception in different ways. In this tutorial, we will learn how to use try-catch in java to handle the exceptions.

Java try-catch block

Java try block contains a set of statements that may result in an exception or produce an unexpected condition. We can either have a try-catch combination or try-finally combination. We cannot have a stand-alone try block alone.

Java catch block contains statements to handle the exception. The catch block always follows the try block and does not exist independently. We can also use multiple catch statements to handle multiple exceptions along with a single try statement. It executes the corresponding catch block that matches the exception type that occurred in the try block.

Syntax of try-catch

try {
  //code that generates exception
}
catch(ExceptionType e) {
  //Handle the exception
}

Syntax of try-finally

try {
  //code that generates exception
}
finally {
//code that executes always
}

Example of try-catch in Java

Now, let’s see an example of a simple try-catch in java. Suppose we have a method that tries to access an array index element that does not exist. First, we will try to execute the code without handling the exception. In this case, during execution, it throws an exception message which user might not understand. Also, it does not execute the second statement inside the method. To handle this unexpected condition and proceed with remaining code execution, we implement the try-catch block.

public class CheckArray {
  
  String[] lang = {"Java","C","C++"};
  
  public void getElement() {
    System.out.println("Index 4: " + lang[4]);
    System.out.println("Index 0: " + lang[0]);
  }

  public static void main(String[] args) {
    CheckArray c = new CheckArray();
    c.getElement();

  }

}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 3
  at CheckArray.getElement(CheckArray.java:6)
  at CheckArray.main(CheckArray.java:11)

Now, we put the code that triggers the exception inside the try block and handles the exception in the catch block. In this case, it throws ArrayIndexOutOfBoundsException since the specified index does not exist. Since the exception is handled using the try-catch, it executes the second statement after the try block.

public class CheckArray {
  
  String[] lang = {"Java","C","C++"};
  
  public void getElement() {
    try {
      System.out.println("Index 4: " + lang[4]);
      
    }
    catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("Exception: The specified index does not exist");
    }
    System.out.println("Index 0: " + lang[0]);	
  }

  public static void main(String[] args) {
    CheckArray c = new CheckArray();
    c.getElement();

  }

}
Exception: The specified index does not exist
Index 0: Java

Multiple catch blocks

A sing try block can have multiple catch blocks to handle multiple exceptions. There can be situations where a single method can generate multiple unexpected conditions. In this case, we need to have different catch blocks to handle the respective exceptions. Based on the exception type produced in the try block, it executes the corresponding catch exception statement.

If there is no exception in the try code, then it does not execute any of the catch statements, which means it ignores all the catch blocks and proceeds with normal program execution.

Syntax

try {
  //code that generates exception
}
catch(ExceptionType1 e) {
  //Handle exception
}
catch(ExceptionType2 e) {
  //Handle exception
}

Example

Now let us see an example of catching multiple exceptions in java using try-catch. Here we are trying to divide a number by 0. Hence it generates ArithemticException and thereby executes the first catch block.

public class MultipleCatchDemo {

  int num[] = new int[3];
  
  public void checkException() {
    try {
      num[0] = 10;
      num[1] = 0;
      int result = num[0]/num[1];
      System.out.println(result);
    }
    catch(ArithmeticException e) {
      System.out.println("Exception: Divide by 0 not allowed");
    }
    catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("Exception: Specified index is not present");
    }
    
  }
  public static void main(String[] args) {
    MultipleCatchDemo m = new MultipleCatchDemo();
    m.checkException();

  }

}
Exception: Divide by 0 not allowed

Now suppose, we change the code and it generates a different exception where we try to access an array element whose index does not exist. In this case, it generates ArrayIndexOutOfBoundsException and executes the second catch block. In a real scenario, we can have a code where each time due to unexpected conditions, different exceptions might occur. Hence it is always better to handle all the exceptions that we expect to occur using a try-catch.

public class MultipleCatchDemo {

  int num[] = new int[3];
  
  public void checkException() {
    try {
      num[0] = 10;
      num[10] = 5;
      int result = num[0]/num[10];
      System.out.println(result);
    }
    catch(ArithmeticException e) {
      System.out.println("Exception: Divide by 0 not allowed");
    }
    catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("Exception: Specified index is not present");
    }
    
  }
  public static void main(String[] args) {
    MultipleCatchDemo m = new MultipleCatchDemo();
    m.checkException();

  }

}
Exception: Specified index is not present

Suppose, code does not generate any type of exception, then it ignores all the catch statements.

public class MultipleCatchDemo {

  int num[] = new int[3];
  
  public void checkException() {
    try {
      num[0] = 10;
      num[1] = 5;
      int result = num[0]/num[1];
      System.out.println(result);
    }
    catch(ArithmeticException e) {
      System.out.println("Exception: Divide by 0 not allowed");
    }
    catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("Exception: Specified index is not present");
    }
    
  }
  public static void main(String[] args) {
    MultipleCatchDemo m = new MultipleCatchDemo();
    m.checkException();

  }

}
2

Handling multiple exceptions in a single try-catch block

We also have the option to handle multiple exceptions in a single try-catch block. For this we use, the | (OR) operator.

Syntax

try {
  //code
}
catch(ExceptionType1 | ExceptionType2 e) {
  //Handle the exception
}

Example

Let’s use the same example we saw above. The only disadvantage of this case is we cannot generate custom messages since we handle both exception types in the same catch block. In the below example we use a system-generated message using the method getMessage of the Throwable class.

public class MultipleCatchDemo {

  int num[] = new int[3];
  
  public void checkException() {
    try {
      num[0] = 10;
      num[10] = 5;
      int result = num[0]/num[1];
      System.out.println(result);
    }
    catch(ArithmeticException  | ArrayIndexOutOfBoundsException e) {
      System.out.println("Exception: " + e.getMessage());
    }
    
  }
  public static void main(String[] args) {
    MultipleCatchDemo m = new MultipleCatchDemo();
    m.checkException();

  }

}
Exception: Index 10 out of bounds for length 3

Handling generic exception using try-catch

When we do not want to handle a specific exception type, we can use the generic exception that handles all types of exceptions using the try-catch. An Exception is the base class of all the exception types. Hence if the code encounters any unexpected condition, it executes this exception if a specific exception is not present.

Syntax

try {
  //code
}
catch(Exception e) {
  //Handle the exception
}

Example of generic Exception using try-catch

In the below example, we have a single try-catch handling generic exception. This means it handles any type of exception that occurs.

public class MultipleCatchDemo {

  int num[] = new int[3];
  
  public void checkException() {
    try {
      num[0] = 10;
      num[10] = 5;
      int result = num[0]/num[1];
      System.out.println(result);
    }
    catch(Exception e) {
      System.out.println("Exception: " + e.getMessage());
    }
  }
  public static void main(String[] args) {
    MultipleCatchDemo m = new MultipleCatchDemo();
    m.checkException();

  }

}
Exception: Index 10 out of bounds for length 3

This is another example where generic exception executes when none of the other exception types matches in the try-catch block. In the try block, we are generating a NumberFormatException condition by parsing incorrect format to Integer. Since we have not handled this exception type, it executes the generic block and prints the system-generated error message.

public class MultipleCatchDemo {

  int num[] = new int[3];
  
  public void checkException() {
    try {
      num[0] = 10;
      num[1] = Integer.parseInt("5 "); //exception code
      int result = num[0]/num[1];
      System.out.println(result);
    }
    
    catch(ArithmeticException e) {
      System.out.println("Exception: Divide by 0 not allowed");
    }
    catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("Exception: Specified index is not present");
    }
    catch(Exception e) {
      System.out.println("Exception: " + e.getMessage());
    }
    
  }
  public static void main(String[] args) {
    MultipleCatchDemo m = new MultipleCatchDemo();
    m.checkException();

  }

}
Exception: For input string: "5 "

Catching exception order using try-catch

Now that we have seen different exception types and generic exceptions using try-catch, next, we need to understand the order in which we must catch the exceptions when a generic one is present. We should always remember to use the generic exception type as the last catch block when there are multiple catch blocks. This is because it will throw a compilation error if we use it in the first since other sub exception types will not be reachable. The Exception class is the parent class of all other exception types.

Example of try-catch exception order

In the below example, we get a compilation error since we use the generic exception type in the first catch block. This is because other exceptions are not reachable.

public class MultipleCatchDemo {

  int num[] = new int[3];
  
  public void checkException() {
    try {
      num[0] = 10;
      num[1] = Integer.parseInt("5 ");
      int result = num[0]/num[1];
      System.out.println(result);
    }
    catch(Exception e) {
      System.out.println("Exception: " + e.getMessage());
    }
    catch(ArithmeticException e) {
      System.out.println("Exception: Divide by 0 not allowed");
    }
    catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("Exception: Specified index is not present");
    }
    
  }
  public static void main(String[] args) {
    MultipleCatchDemo m = new MultipleCatchDemo();
    m.checkException();

  }

}
Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
  Unreachable catch block for ArithmeticException. It is already handled by the catch block for Exception
  Unreachable catch block for ArrayIndexOutOfBoundsException. It is already handled by the catch block for Exception

  at MultipleCatchDemo.checkException(MultipleCatchDemo.java:15)
  at MultipleCatchDemo.main(MultipleCatchDemo.java:29)

try-catch-finally block

Along with the try-catch block, we can include a finally block towards the end. Irrespective of whether an exception occurs or not, it executes the code inside the finally block. This is normally used to close an object which we have created in the starting. For example, closing the FileReader object, etc.

Example: when there is no exception

In the below example, we can see that the finally block executes even when there is no exception generated in the try-catch block.

public class FinallyDemo{
  
  int a = 10;
  int b = 2;
  public void divide() {
    try {
      int result = a/b;
      System.out.println("Result: " + result);
    }
    catch(ArithmeticException e) {
      System.out.println("Exception: Division by 0 is not allowed");
    }
    finally {
      System.out.println("Divide method executed");	
    }
    
  }

  public static void main(String[] args) {
    FinallyDemo f = new FinallyDemo();
    f.divide();

  }

}
Result: 5
Divide method executed

Example: When an exception occurs

Below is an example of executing the finally block when an exception occurs and is handled in a try-catch block.

public class FinallyDemo{
  
  int a = 10;
  int b = 0;
  public void divide() {
    try {
      int result = a/b;
      System.out.println("Result: " + result);
    }
    catch(ArithmeticException e) {
      System.out.println("Exception: Division by 0 is not allowed");
    }
    finally {
      System.out.println("Divide method executed");	
    }
    
  }

  public static void main(String[] args) {
    FinallyDemo f = new FinallyDemo();
    f.divide();

  }

}
Exception: Division by 0 is not allowed
Divide method executed

Internal working of try-catch-finally

The below flow chart will help us clearly understand the working flow of try-catch-finally statements.

try catch in Java

Nested try-catch block

When there is a try-catch block within another try-catch block, we call it a nested try-catch block. When an exception occurs inside the inner try block, it first checks if it is handled by the inner catch block. If it is not handled, then the control goes to the parent catch block and checks the exception. If present, it executes the parent catch block.

Syntax

//Main try block
try {
   //code
   //Inner try block
   try {
   //code
   }
   //Inner catch block
   catch(Exception1 e) {
   //Handle exception
   }
//Main catch block
catch(Exception2 e) {
//Handle exception
}

Working of nested try-catch block

try catch in java

Example of nested try-catch

In this example, we have 2 try-catch blocks. The first try block does not generate an exception, while the second try generates ArithemticException. In the parent catch block, it handles ArithmeticException while the child catch block handles ArrayIndexOutOfBoundsException. Now during execution, when it executes the second try block, it checks if the exception is handled in the corresponding catch. Since it does not contain the required type, it checks the parent catch block which matches the exception type and executes the same.

public class NestedDemo {

  public static void main(String[] args) {
    int a = 10;
    int b = 5;
    
    try {
      int result = a/b;
      System.out.println("Result: " + result);
      try {
        b = 0;
        result = a/b;
        System.out.println("Result: " + result);
      }
      catch(ArrayIndexOutOfBoundsException e) {
        System.out.println("Exception: " + e.getMessage());
      }
    }
    catch(ArithmeticException e) {
      System.out.println("Exception: " + e.getMessage());
    }
  }

}
Result: 2
Exception: / by zero

Now let us see another example where both the try statements produce an exception. In this case, when it executes the first try block, it encounters a NumberFormatException and executes the corresponding main catch block. Since the parent try block contains an exception, it does not execute the inner try block. This is the reason that it did not print the ArithmeticException statement of the inner try block.

public class NestedDemo {

  public static void main(String[] args) {
    int a = 10;
    int b = 5;
    
    try {
      int result = Integer.parseInt(null);
      System.out.println("Result: " + result);
      try {
        b = 0;
        result = a/b;
        System.out.println("Result: " + result);
      }
      catch(ArithmeticException e) {
        System.out.println("Exception: Arithmetic Exception");
      }
    }
    catch(NumberFormatException e) {
      System.out.println("Exception: Number format exception");
    }
    System.out.println("End of method");
  }

}
Exception: Number format exception
End of method

 

Reference

Translate »