Site Search:

Use catch, multi-catch, and finally clauses

Back>

In OCAJP Handling Exceptions, we studied try, catch, finally clause, here we add multi-catch.

try-catch-finally
try-catch-finally

Java 7 allows programmer to catch multiple exceptions i the same catch block, also known as multi-catch.

OCPJP>cat MultiCatchDemo.java 
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.NumberFormat;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.Locale;

public class MultiCatchDemo {
    public static void main(String...args) {
        try {
            LocalDate date = LocalDate.parse("2017-10-19"); 
            //LocalDate date = LocalDate.parse("can not parse"); //could throw RuntimeException
            Path path = Paths.get("MultiCatchDemo.java"); 
            Number number = NumberFormat.getInstance(Locale.FRANCE).parse("123.99"); //can throw ParseException
            int size = Files.readAllLines(path).size();  //can throw IOException
            System.out.println(date.toString() + " read " + size + " lines with France money " + number);
            throw new NullPointerException("nobody catch");
        } catch(DateTimeParseException | FileNotFoundException | ParseException e) {
            e.printStackTrace();
        } catch(NumberFormatException | IOException e ) {
            System.out.println("=======2======");
            e.printStackTrace();
        } 
    }

}
OCPJP>
OCPJP>
OCPJP>javac MultiCatchDemo.java 
OCPJP>java MultiCatchDemo
2017-10-19 read 30 lines with France money 123
Exception in thread "main" java.lang.NullPointerException: nobody catch
at MultiCatchDemo.main(MultiCatchDemo.java:21)

OCPJP>


A few things to notice here:

  • the multi-catch block is not same as try{} catch(Exception e) {}. The multi-catch won't catch any other exceptions not declared such as RuntimeExceptions, the catch(Exception e) will catch all the exceptions including RuntimeException.
  • the syntax is catch(Exception1 | Exception2 | Exception3 e). Syntax like catch(Exception1 e | exception2 e | Exception3 e3) won't compile. 
  • Exceptions in multi-catch block can not be subclasses, the following code won't compile.
try { 
    throw new EOFException(); 
} catch(FileNotFoundException | IOException) {}

  • multi-catch block can not catch any RuntimeException, however, only checked exceptions that have the potential to be thrown are allowed to be caught. The following code won't compile.
try {
    throw new IllegalStateException();
} catch (ArrayIndexOutOfBoundsException | SQLException e) {}

  • like regular Exception, multi-catch obeys the same rules: more general superclasses must be caught after their subclasses, list the same exception type more than once in the same try statement is not allowed.
You can re throw exceptions in the catch block and multi-catch block. Notice if you don't use multi-catch, but use superClass Exception instead, you may catch those Exceptions you are not intend to handle.

OCPJP>cat RethrowDemo1.java 
import java.io.IOException;
import java.sql.SQLException;

public class RethrowDemo1 {
    public static void aMethod() throws IOException, SQLException, IndexOutOfBoundsException {
        throw new IOException("from aMethod");
    }
    
    //add additional Exceptions from signature
    public static void aMethod2() throws IOException, SQLException, IndexOutOfBoundsException, UnsupportedOperationException {
        throw new UnsupportedOperationException("from aMethod2");
    }
    
    //remove some Exceptions from signature
    public static void aMethod3() throws IOException, SQLException {
        throw new UnsupportedOperationException("from aMethod3");
    }
    
    public static void wrapper1() throws IOException, SQLException, IndexOutOfBoundsException {
        try{
            aMethod();
        } catch(IOException | SQLException | IndexOutOfBoundsException e) {
            System.out.println("caught " + e.getClass() + ", rethrown from wrapper1");
            throw e;
        }
    }
    
    public static void wrapper2() throws IOException, SQLException, IndexOutOfBoundsException {
        try{
            aMethod();
        } catch(Exception e) {
            System.out.println("caught " + e.getClass() + ", rethrown from wrapper2");
            throw e;
        }
    }
    
    public static void wrapper3() throws IOException, SQLException, IndexOutOfBoundsException, UnsupportedOperationException {
        try{
            aMethod2();
        } catch(IOException | SQLException | IndexOutOfBoundsException | UnsupportedOperationException e) { //have to add more
            System.out.println("caught " + e.getClass() + ", rethrown from wrapper3");
            throw e;
        }
    }
    
    public static void wrapper4() throws IOException, SQLException, IndexOutOfBoundsException, UnsupportedOperationException {
        try{
            aMethod2();
        } catch(Exception e) {  //no change
            System.out.println("caught " + e.getClass() + ", rethrown from wrapper4");
            throw e;
        }
    }
    
    public static void wrapper5() throws IOException, SQLException {
        try{
            aMethod3();
        } catch(IOException | SQLException e) { //have to remove some to avoid catching unwanted
            System.out.println("caught " + e.getClass() + ", rethrown from wrapper5");
            throw e;
        }
    }
    
    public static void wrapper6() throws IOException, SQLException {
        try{
            aMethod3();
        } catch(Exception e) { //won't work, it caught unwanted exceptions
            System.out.println("caught " + e.getClass() + ", rethrown from wrapper6");
            throw e;
        }
    }
    
    public static void main(String args[]) {
        try {
            wrapper1();
        } catch (IndexOutOfBoundsException | IOException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        try {
            wrapper2();
        } catch (IndexOutOfBoundsException | SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        try {
            wrapper3();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        try {
            wrapper4();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        try {
            wrapper5();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        try {
            wrapper6();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
OCPJP>
OCPJP>
OCPJP>javac RethrowDemo1.java 
OCPJP>java RethrowDemo1
caught class java.io.IOException, rethrown from wrapper1
java.io.IOException: from aMethod
at RethrowDemo1.aMethod(RethrowDemo1.java:6)
at RethrowDemo1.wrapper1(RethrowDemo1.java:21)
at RethrowDemo1.main(RethrowDemo1.java:75)
caught class java.io.IOException, rethrown from wrapper2
java.io.IOException: from aMethod
at RethrowDemo1.aMethod(RethrowDemo1.java:6)
at RethrowDemo1.wrapper2(RethrowDemo1.java:30)
at RethrowDemo1.main(RethrowDemo1.java:83)
caught class java.lang.UnsupportedOperationException, rethrown from wrapper3
java.lang.UnsupportedOperationException: from aMethod2
at RethrowDemo1.aMethod2(RethrowDemo1.java:11)
at RethrowDemo1.wrapper3(RethrowDemo1.java:39)
at RethrowDemo1.main(RethrowDemo1.java:91)
caught class java.lang.UnsupportedOperationException, rethrown from wrapper4
java.lang.UnsupportedOperationException: from aMethod2
at RethrowDemo1.aMethod2(RethrowDemo1.java:11)
at RethrowDemo1.wrapper4(RethrowDemo1.java:48)
at RethrowDemo1.main(RethrowDemo1.java:97)
java.lang.UnsupportedOperationException: from aMethod3
at RethrowDemo1.aMethod3(RethrowDemo1.java:16)
at RethrowDemo1.wrapper5(RethrowDemo1.java:57)
at RethrowDemo1.main(RethrowDemo1.java:103)
caught class java.lang.UnsupportedOperationException, rethrown from wrapper6
java.lang.UnsupportedOperationException: from aMethod3
at RethrowDemo1.aMethod3(RethrowDemo1.java:16)
at RethrowDemo1.wrapper6(RethrowDemo1.java:66)
at RethrowDemo1.main(RethrowDemo1.java:109)

OCPJP>

a rule of Exception handling is to know what to catch and what to throw. Throwing exceptions you can not handle is not guilty, it is responsible.