java 7:详解try-with-resources的使用_java7 语法糖 try-with-resource的使用

在java7之前我们打开/关闭JDBC连接,打开/关闭文件输入输出流时都会采用一套固定的套路代码来打开资源 使用资源 关闭资源。类似于下面的这段:

InputStream inputStream = null;

OutputStream outputStream = null;

try {

//打开输入输出流

inputStream = new FileInputStream("");

outputStream = new FileOutputStream("");

byte[] temp = new byte[1024];

int len = -1;

while ((len = inputStream.read(temp)) != -1) {

outputStream.write(temp);

}

outputStream.flush();

} catch (Exception e) {

//包装异常或者抛出或者打印输出

} finally {

//关闭输入输出流

if (outputStream != null) {

try {

outputStream.close();

} catch (IOException ioE) {

//关闭资源时发生异常

ioE.printStackTrace();

}

}

if (inputStream != null) {

try {

inputStream.close();

} catch (IOException ioE) {

//关闭资源时发生异常

ioE.printStackTrace();

}

}

}

上面这段代码中我最不喜欢写的就是关闭资源的写法显得特别的臃肿和多余。但是在JAVA7 中有一个新的 try-with-resource 的语法糖,该语法糖就简化了上面这种开启关闭资源的写法,我们不用自己写代码来关闭这些资源了,语法糖能够帮助我们自定关闭。该语法糖适用于实现了java.lang.AutoCloseable 或者 java.io.Closeable的资源类,这俩接口都需要实现一个close方法。

自定义资源类:

public class MyResouce implements AutoCloseable {

private String name;

public MyResouce(String name){

this.name=name;

}

@Override

public void close() throws Exception {

System.out.println(name+"资源被关闭了");

}

public void openResouse(){

System.out.println(name+"资源被打开了");

}

public class TryWithResourceTest {

@Test

public void test() {

try (MyResouce myResouce = new MyResouce("资源1");) {

myResouce.openResouse();

System.out.println("=======处理了一大堆事情=======");

TimeUnit.SECONDS.sleep(2);

System.out.println("=======事情处理完了=======");

} catch (Exception e) {

e.printStackTrace();

}

}

}

结果:

资源1资源被打开了

=======处理了一大堆事情=======

=======事情处理完了=======

资源1资源被关闭了

看到了吧,close方法是被自动调用的,不需要我们自己写代码调用。也可以使用多个资源最后关闭的时候是按照构建FILO的顺序进行资源关闭的。也就是在try()括号内先实例化的后关闭,后实例化的先关闭。

public class TryWithResourceTest {

@Test

public void test() {

try (MyResouce myResouce = new MyResouce("资源1");MyResouce myResouce2 = new MyResouce("资源2");) {

myResouce.openResouse();

myResouce2.openResouse();

System.out.println("=======处理了一大堆事情=======");

TimeUnit.SECONDS.sleep(2);

System.out.println("=======事情处理完了=======");

} catch (Exception e) {

e.printStackTrace();

}

}

}

结果:

资源1资源被打开了

资源2资源被打开了

=======处理了一大堆事情=======

=======事情处理完了=======

资源2资源被关闭了

资源1资源被关闭了

在旧try finally 写法中的资源关闭时如果try块的处理逻辑和finally块中关闭资源代码同时发生异常,则向外抛出的的异常只有finally块的异常,try 块的异常会被屏蔽掉。这可不是我们所想要的。用了try-with-resource 之后就可以将所有的异常都抛出。

public class MyResouce implements AutoCloseable {

private String name;

public MyResouce(String name){

this.name=name;

}

@Override

public void close() throws Exception {

System.out.println(name+"正在关闭资源...");

throw new IOException(name+"资源在关闭时发生异常");

}

public void openResouse() throws Exception {

System.out.println(name+"资源被打开了");

}

}

public class TryWithResourceTest {

@Test

public void test() {

try{

testExceptionThrow();

}catch (Exception ex){

ex.printStackTrace();

}

}

private void testExceptionThrow() throws Exception {

MyResouce myResouce1=new MyResouce("资源1");

try{

myResouce1.openResouse();

throw new Exception("业务处理异常了");

}finally {

if(myResouce1!=null){

myResouce1.close();

}

}

}

}

结果:

java.io.IOException: 资源1资源在关闭时发生异常

at com.sane.mu.MyResouce.close(MyResouce.java:15)

at com.sane.mu.TryWithResourceTest.testExceptionThrow(TryWithResourceTest.java:42)

at com.sane.mu.TryWithResourceTest.test(TryWithResourceTest.java:27)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)

at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)

at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)

at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)

at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)

at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)

at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)

at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)

at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)

at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)

at org.junit.runners.ParentRunner.run(ParentRunner.java:363)

at org.junit.runner.JUnitCore.run(JUnitCore.java:137)

at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)

at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)

at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)

at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

资源1资源被打开了

资源1正在关闭资源...

下面是使用try-with-resource 语法糖的写法,此处同样会抛出两个异常,而我们这次可以看到所有的异常信息。

public class TryWithResourceTest {

@Test

public void test() {

try{

testExceptionThrow();

}catch (Exception ex){

ex.printStackTrace();

}

}

private void testExceptionThrow() throws Exception {

try(MyResouce myResouce1=new MyResouce("资源1");){

myResouce1.openResouse();

throw new Exception("业务处理异常了");

}

}

}

资源1资源被打开了

资源1正在关闭资源...

java.lang.Exception: 业务处理异常了

at com.sane.mu.TryWithResourceTest.testExceptionThrow(TryWithResourceTest.java:38)

at com.sane.mu.TryWithResourceTest.test(TryWithResourceTest.java:27)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)

at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)

at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)

at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)

at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)

at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)

at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)

at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)

at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)

at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)

at org.junit.runners.ParentRunner.run(ParentRunner.java:363)

at org.junit.runner.JUnitCore.run(JUnitCore.java:137)

at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)

at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)

at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)

at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Suppressed: java.io.IOException: 资源1资源在关闭时发生异常

at com.sane.mu.MyResouce.close(MyResouce.java:15)

at com.sane.mu.TryWithResourceTest.testExceptionThrow(TryWithResourceTest.java:39)

... 23 more

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值