Java | try-with-resources语句

try-with-resources是Java SE7的一个新特性。

用try-with-resources语句确保资源关闭

try-with-resources语句是一种声明了一种或多种资源的try语句。资源是指在程序用完了之后必须要关闭的对象。任何实现了AutoCloseable接口和Closeable接口的对象,都可以当作资源使用。

在Java SE7之前,需要用finally代码块来手动关闭资源,无论try语句正常结束还是异常结束,都会执行finally代码块的内容。example1从键盘读取一行输入,并在finally中释放BufferedReader资源。

// example1
static String myReadLineWithFinally() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
                return br.readLine();
        } finally {
                if (br != null) {
                        br.close();
                }
        }

}

复制代码

Java SE7以后,可以用try-with-resources代替try-catch-finally。在example2中,try-with-resources语句声明的是BufferedReader资源。声明语句紧跟着try关键字后的圆括号里。无论try语句是正常结束还是异常结束(比如readLine方法抛出一个IOException异常),它都会被自动关闭。

// example2
static String myReadLine() throws IOException {
        try (BufferedReader br =
                        new BufferedReader(new InputStreamReader(System.in));) {
                return br.readLine();
        }

}
复制代码

example3用try-with-resources自动关闭java.sql.Connection对象和java.sql.Statement,关闭的顺序是先Statement,后Connection

// example3
    try (Connection con = DriverManager.getConnection("jdbc:calcite:", config)) {
      try (Statement stmt = con.createStatement()) {
        try (ResultSet resultSet = stmt.executeQuery(sql)) {
          output(resultSet);
          }
        }
      }
复制代码

也可以自己创建资源(只需要实现java,lang.AutoCloseable接口或java.io.Closeable接口),然后在try-with-resources结构里声明、使用自己的资源。

// example4
public class Test{
	public static void main(String[] args) throws Exception {
		try (MyResources mr = new MyResources();) {
			mr.work();
		}
//		控制台输出
//		MyResources is working
//		MyResources is closed 

		
	}
	
}
class MyResources implements AutoCloseable {
	
	public void work() {
		System.out.println("MyResources is working");
	}

	@Override
	public void close() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("MyResources is closed ");
	}
	
}
复制代码

被压抑的异常

在try-finally语句中,如果try和finally中都发生异常,那么finally只会抛出发生在finally中的异常,try里的异常将会被抑制。如example3所示,会抛出java.io.IOException: Stream closed异常,而java.lang.ArithmeticException: / by zero异常被抑制。

// example5
static String myReadLineWithFinally() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
                int x = 1 / 0; //  java.lang.ArithmeticException: / by zero
                return br.readLine();
        } finally {
                if (br != null) {
                        br.close();
                }
                br.read(); //  java.io.IOException: Stream closed
        }
}
复制代码

在try-with-resources中,如果在圆括号里和代码块里都发生了异常,圆括号里的异常会向外传播,这与旧风格相反。在example4中,抛出的是 java.io.FileNotFoundException而不是java.lang.ArithmeticException: / by zero

// example6
static void printFile() throws FileNotFoundException, IOException {
        try (FileInputStream input = new FileInputStream("not_exist.txt")) {//  java.io.FileNotFoundException:
                int x = 1 / 0;
        }
}
复制代码

当然,try-with-resouces语句也可以有catch和finally代码块。在try-with-resources语句中,任何的catch和finally代码块都在所有被声明的资源被关闭后执行。

使用多个资源

可以在try-with-resources中声明多个资源,这些资源都能被自动地关闭。关闭的顺序是创建顺序的逆序。如example5,先关闭BufferedReader,再关闭FileInputStream

// example7
static void multiSources() throws IOException {
        try (FileInputStream input = new FileInputStream("D://file.txt");
                        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));) {
                int data = input.read();
                String line = br.readLine();
                System.out.println(data + " " + line);
        }
}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享