JDK7资源自动释放的介绍与深入思考

 

 
       资源自动释放是JDK7的一个重大改进。 jdk7提供了try-with-resources,可以自动关闭相关的资源(只要该资源实现了AutoCloseable接口,jdk7为绝大部分资源对象都实现了这个接口)。
 

try-with-resources 语句是一个声明了1到多个资源的try语句。资源是指这个try执行完成后必需close掉的对象,比如connection, resultset等。

 

try-with-resources 语句会确保在try语句结束时关闭所有资源。实现了java.lang.AutoCloseablejava.io.Closeable的对象都可以做为资源。

 

     下面是一个例子,它会从一个文件中读出首行文本,这里使用了 BufferedReader 的实例来读取数据, BufferedReader 是一个资源,它应该在程序完成时被关闭。
     
static String readFirstLineFromFile(String path) throws IOException {  
   try (BufferedReader br = new BufferedReader(new FileReader(path))) {  
      return br.readLine();  
   }  
}  
 

       可以看到,由于BufferedReader被定义在try-with-resource 语句中,因此不管try代码块是正常完成或是出现异常,这个BufferedReader 的实例都将被关闭。

 

       而在java7之前的版本中,需要使用finally 代码块来确保资源被关闭(不管try正常完成还是出现异常)。
 
    static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {  
      BufferedReader br = new BufferedReader(new FileReader(path));  
      try {  
        return br.readLine();  
      } finally {  
        if (br != null) br.close();  
      }  
    }  
 
 
         以上是JDK7自动关闭的一个总结,实例都是使用的其他人文章里的。看到这些问题,让我心里一动,提出一个我的问题是, 自动释放机制能否区分是正常释放还是异常释放?具体的说,就是这个释放,是try块正常完成了还是出现异常了需要释放?
      之所以提出这个问题,就是因为资源释放是代码非常容易出现bug的场景,而异常情况下是否能合理清理资源、释放资源又是其中最最容易出错的地方。
 
从数据库相关开发的角度看,例如下面的代码:
Connection connection = null;
Statement statement = null;

try{
    connection = pool.getConnection();
    statement = connection.createStatemnet();
    boolean executionStatus= statement.execute(“query”);
}catch(Exception e){
    //Block of code for handle the exception
    e.printStacktrace();
}finally{
    try{
        statement.close();
        connection.close();
    }catch(Exception e){
    //block of statements for handle exceptions.
}
 
在JDK7中简化成
Connection connection = null;
Statement statement = null;

try(//请注意这里的小括号,不是大括号
    connection =   pool.getConnection();
    statement = connection.createStatemnet()
)
{
    boolean executionStatus= statement.execute(“query”);
}catch(Exception e){
    //block of statements for handles the exceptions
}
 
在上面的情况下,如果需要事务控制,变成:
Connection connection = null;
Statement statement = null;

try(//请注意这里的小括号,不是大括号
    connection =   pool.getConnection();
    statement = connection.createStatemnet()
)
{
    boolean executionStatus= statement.execute(“query”);
	conn.commit();
}catch(Exception e){
    //block of statements for handles the exceptions
	conn.rollback();
}
 
 
       正常执行,到最后,需要提交事务;异常关闭,需要先回滚,然后再关闭。这个事务的控制还得要自己写代码才行。
      所以对Oracle提供的java.lang.AutoCloseable接口有一些疑问,为什么只是提供了一个这样的接口供实现:
 
 void close()
 
为什么不是:
 
     normalClose();//正常关闭
     errorClose();//异常关闭
 
 
     如果是接口这样设计和实现,那么开发可以变得非常简单了。
       我举的数据库连接只是一个示例(事务是一个,再有一个是 如果出现异常,那么连接很有可能就不能回池了,只能销毁,因为是坏了的连接)。还有很多类似场景,正常关闭和错误关闭都需要外边很多其他额外工作,不简单的是close那么一件事。
 
      如果有这样的接口,那么,在开发过程中,在基础类实现中,前期把这些资源的释放(创建还好说, 释放至关紧要)都设计实现好,把AutoCloseable需要的两个接口(可惜现在Java只有一个)实现好,那么就会很大程度上减少后期团队开发过程中出现错误。 

你可能感兴趣的:(JDK7资源自动释放的介绍与深入思考)