try-with-resources语句可确保在语句末尾关闭每个资源。 任何实现java.lang.AutoCloseable或java.io.Closeable接口的对象都可以用作资源。
在尝试使用资源 (在Java 7之前)处理SQL语句或ResultSet或Connection对象或其他IO对象之前,必须显式关闭资源。 所以一个人会写类似:
try{//Create a resource- R
} catch(SomeException e){//Handle the exception
} finally{//if resource R is not null thentry{//close the resource}catch(SomeOtherException ex){}
}
我们必须显式关闭资源,从而添加更多代码行。 在极少数情况下,开发人员会忘记关闭资源。 因此,为了克服这些问题和其他问题,Java 7中引入了try-with-resources 。
让我们看一个示例,说明如何在Java 7之前的版本中使用try..catch…。让我创建2个自定义异常-ExceptionA和ExceptionB。 这些将在整个示例中使用。
public class ExceptionA extends Exception{public ExceptionA(String message){super(message);}
}
public class ExceptionB extends Exception{public ExceptionB(String message){super(message);}
}
让我们创建一些资源,例如OldResource,它有两种方法– doSomeWork():完成一些工作,close():完成关闭。 请注意,这描述了通用资源的使用-做一些工作,然后关闭资源。 现在,每个操作doSomeWork和close都会引发异常。
public class OldResource{public void doSomeWork(String work) throws ExceptionA{System.out.println("Doing: "+work);throw new ExceptionA("Exception occured while doing work");}public void close() throws ExceptionB{System.out.println("Closing the resource");throw new ExceptionB("Exception occured while closing");}
}
让我们在示例程序中使用此资源:
public class OldTry {public static void main(String[] args) {OldResource res = null;try {res = new OldResource();res.doSomeWork("Writing an article");} catch (Exception e) {System.out.println("Exception Message: "+e.getMessage()+" Exception Type: "+e.getClass().getName());} finally{try {res.close();} catch (Exception e) {System.out.println("Exception Message: "+e.getMessage()+" Exception Type: "+e.getClass().getName());}}}
}
输出:
Doing: Writing an article
Exception Message: Exception occured while doing work Exception Type: javaapplication4.ExceptionA
Closing the resource
Exception Message: Exception occured while closing Exception Type: javaapplication4.ExceptionB
该程序很简单:创建一个新资源,使用它,然后尝试关闭它。 可以看看那里多余的代码行数。
现在,让我们使用Java 7的try-with-resource结构实现相同的程序。 为此,我们需要一个新资源– NewResource。 在Java 7中,新接口为java.lang.AutoCloseable 。 那些需要关闭的资源将实现此接口。 所有较旧的IO API,套接字API等都实现了Closeable接口-这意味着可以关闭这些资源。 使用Java 7, java.io.Closeable实现AutoCloseable 。 因此,一切正常,而不会破坏任何现有代码。
下面的NewResource代码:
public class NewResource implements AutoCloseable{String closingMessage;public NewResource(String closingMessage) {this.closingMessage = closingMessage;}public void doSomeWork(String work) throws ExceptionA{System.out.println(work);throw new ExceptionA("Exception thrown while doing some work");}public void close() throws ExceptionB{System.out.println(closingMessage);throw new ExceptionB("Exception thrown while closing");}public void doSomeWork(NewResource res) throws ExceptionA{res.doSomeWork("Wow res getting res to do work");}
}
现在,使用try-with-resource在示例程序中使用NewResource:
public class TryWithRes {public static void main(String[] args) {try(NewResource res = new NewResource("Res1 closing")){res.doSomeWork("Listening to podcast");} catch(Exception e){System.out.println("Exception: "+e.getMessage()+" Thrown by: "+e.getClass().getSimpleName());}}
}
输出:
Listening to podcast
Res1 closing
Exception: Exception thrown while doing some work Thrown by: ExceptionA
上面要注意的一件事是,关闭方法抛出的异常被worker方法抛出的异常所抑制。
因此,您可以立即注意到这两种实现之间的差异,一种实现最终使用try ... catch ...,另一种使用try-with-resource。 在上面的示例中,仅一个资源被声明为已使用。 一个人可以在try块中声明和使用多个资源,也可以嵌套这些try-with-resources块。
随之,在java.lang.Throwable类中添加了一些新方法和构造函数,所有这些方法都与抑制与其他异常一起抛出的异常有关。 最好的例子是-try块抛出的ExceptionA会被finally(关闭资源时)抛出的ExceptionB抑制,这是Java 7之前的行为。
但是,对于Java 7,抛出的异常会跟踪它在被捕获/处理的过程中被抑制的异常。 因此,前面提到的示例可以重新陈述如下。 由close方法抛出的ExceptionB被添加到由try块抛出的ExceptionA的抑制异常列表中。
让我用以下示例说明您嵌套的try-with-resources和Suppressed异常。
嵌套的尝试资源
public class TryWithRes {public static void main(String[] args) {try(NewResource res = new NewResource("Res1 closing");NewResource res2 = new NewResource("Res2 closing")){try(NewResource nestedRes = new NewResource("Nestedres closing")){nestedRes.doSomeWork(res2);}} catch(Exception e){System.out.println("Exception: "+e.getMessage()+" Thrown by: "+e.getClass().getSimpleName());}}
}
上面的输出将是:
Wow res getting res to do work
Nestedres closing
Res2 closing
Res1 closing
Exception: Exception thrown while doing some work Thrown by: ExceptionA
注意关闭资源的顺序,最新的优先。 还要注意,抑制了每个close()操作引发的异常。
让我们看看如何检索被抑制的异常:
禁止的异常
public class TryWithRes {public static void main(String[] args) {try(NewResource res = new NewResource("Res1 closing");NewResource res2 = new NewResource("Res2 closing")){try(NewResource nestedRes = new NewResource("Nestedres closing")){nestedRes.doSomeWork(res2);}} catch(Exception e){System.out.println("Exception: "+e.getMessage()+" Thrown by: "+e.getClass().getSimpleName());if (e.getSuppressed() != null){for (Throwable t : e.getSuppressed()){System.out.println(t.getMessage()+" Class: "+t.getClass().getSimpleName());}}}}
}
上面代码的输出:
Wow res getting res to do work
Nestedres closing
Res2 closing
Res1 closing
Exception: Exception thrown while doing some work Thrown by: ExceptionA
Exception thrown while closing Class: ExceptionB
Exception thrown while closing Class: ExceptionB
Exception thrown while closing Class: ExceptionB
getSuppressed()方法用于检索被抛出的异常阻止的异常。 还向Throwable类添加了新的构造函数,该构造函数可用于启用或禁用异常抑制。 如果禁用,则不会跟踪任何抑制的异常。
参考: Java 7项目硬币: Try -with-resources,以及我们的JCG合作伙伴 Mohamed Sanaulla在Experiences Unlimited Blog 上的示例进行了解释 。
- 速览Java 7 MethodHandle及其用法
- JDK中的设计模式
- 了解和扩展Java ClassLoader
- Java内存模型–快速概述和注意事项
翻译自: https://www.javacodegeeks.com/2011/07/java-7-try-with-resources-explained.html