ablog

不器用で落着きのない技術者のメモ

try-catch-finally を入れ子にしても外側の finally は通る

Java で try-catch-finally が入れ子になっているとき、内側の try で例外が発生した場合に外側の finally を通ることを確認してみた。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.SQLException;
import h.Hoge2;

public class Hoge {
	public static void main(String args[]) {
		Connection conn = null;
		try {
			Class.forName ("oracle.jdbc.driver.OracleDriver");
			conn = DriverManager.getConnection
				("jdbc:oracle:thin:@192.168.45.101:1521:orcl","scott","tiger");
			Hoge2 h2 = new Hoge2(conn);
			h2.insert();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
				if (conn != null) {
		  			conn.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
			System.out.println("finally at Hoge#main()");
		}
	}
}
package h;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.SQLException;

public class Hoge2 {
        private Connection conn = null;

        public Hoge2(Connection conn) {
                this.conn = conn;
        }

        public void insert() {
                Statement stmt = null; 
                try {
                        stmt = conn.createStatement();
                        int resultCount = stmt.executeUpdate
                                ("insert into emp(id, name) values('001','scott')");
                        conn.commit();
                        if (resultCount == 1) {
                                System.out.println("A row was inserted successfully."); 
                        } else {
                                System.out.println("Failed to insert a row.");
                        }
                } catch(SQLException e) {
                        e.printStackTrace();
                } finally {
                        try {
                                if (stmt != null) {
                                        stmt.close();
                                }
                        } catch(SQLException e) {
                                e.printStackTrace();
                        }
                }
                System.out.println("finally at Hoge2#insert()");
        }
}
$ $ find . -ls
1081255        0 drwxr-xr-x    6 yohei    staff         204  4  4 22:03 .
1082543        0 drwxr-xr-x    3 yohei    staff         102  4  4 22:03 ./h
1093667        8 -rw-r--r--    1 yohei    staff        1392  4  4 21:58 ./h/Hoge2.java
1093655        8 -rw-r--r--    1 yohei    staff         743  4  4 21:57 ./Hoge.java
1081926     3040 -rw-r--r--    1 yohei    staff     1555682  3 12 19:21 ./ojdbc14.jar
$ javac h/Hoge2.java 
$ javac Hoge.java 
  • 実行してみる。
$ export CLASSPATH=.:$CLASSPATH:ojdbc14.jar 
$ java Hoge
A row was inserted successfully.
finally at Hoge2#insert()
finally at Hoge#main()
  • もう一回実行すると、一意制約違反で例外発生。ちゃんと Hoge#main() の finally を通っている。
$ java Hoge
java.sql.SQLException: ORA-00001: unique constraint (SCOTT.SYS_C004424) violated

	at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
	at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
	at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210)
	at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:961)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190)
	at oracle.jdbc.driver.OracleStatement.executeUpdateInternal(OracleStatement.java:1657)
	at oracle.jdbc.driver.OracleStatement.executeUpdate(OracleStatement.java:1626)
	at h.Hoge2.insert(Hoge2.java:18)
	at Hoge.main(Hoge.java:15)
finally at Hoge2#insert()
finally at Hoge#main()