9-资源关闭
为什么有些资源要手动关闭?
主要跟垃圾回收(GC特点)有关.
垃圾回收机制只负责回收堆内存的资源,不会回收任何物理资源.
程序无法精确控制垃圾回收动作具体时间.
在垃圾回收之前,总会先调用它的finalize方法.
常见需手动释放的物理资源
文件/流资源
套接字资源
数据库连接资源
资源不手动释放会引起的问题
资源被长时间无效占用
超过最大限制,将无资源可用
导致系统无法正常运行
JDK7之前,释放资源的方式
1 import org.junit.Test; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 8 public class FileCopyTest { 9 10 @Test 11 public void copyFile() { 12 /** 13 * 1.创建输入/输出流 14 * 2.执行文件拷贝,读取文件内容,写入到另一个文件中 15 * 3.**关闭文件流资源** 16 */ 17 18 //定义输入路径和输出路径 19 String originalUrl = "lib/FileCopyTest.java"; 20 String targetUrl = "targetTest/target.txt"; 21 22 FileInputStream originalFileInputStream = null; 23 FileOutputStream targetFileOutputStream = null; 24 25 try { 26 //初始化输入输出流对象 27 originalFileInputStream = new FileInputStream(originalUrl); 28 targetFileOutputStream = new FileOutputStream(targetUrl); 29 30 //读取字节信息 31 int content; 32 33 //迭代,读取/写入字节 34 while((content = originalFileInputStream.read()) != -1) { 35 targetFileOutputStream.write(content); 36 } 37 } catch (FileNotFoundException e) { 38 e.printStackTrace(); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 } finally { 42 if(targetFileOutputStream != null) { 43 try { 44 targetFileOutputStream.close(); 45 } catch (IOException e) { 46 e.printStackTrace(); 47 } 48 } 49 50 if(originalFileInputStream != null) { 51 try { 52 originalFileInputStream.close(); 53 } catch (IOException e) { 54 e.printStackTrace(); 55 } 56 } 57 } 58 } 59 }
JDK7之后,释放资源的方式
TWR(Try-With-Resource)
java7引入新特性
优雅关闭资源
一种Java语法糖
多资源自动关闭
实现AutoCloseable接口
避免异常屏蔽
代码
1 import org.junit.Test; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 8 /** 9 * @description: try-with-resource 10 */ 11 public class NewFileCopyTest { 12 13 @Test 14 public void copyFile(){ 15 //定义输入和输出路径 16 String originalUrl = "lib/NewFileCopyTest.java"; 17 String targetUrl = "targetTest/new.txt"; 18 19 try( 20 //初始化输入输出流对象 21 FileInputStream originalFileInputStream = new FileInputStream(originalUrl); 22 FileOutputStream targetFileOutputStream = new FileOutputStream(targetUrl); 23 ){ 24 //读取字节信息 25 int content; 26 27 while ((content = originalFileInputStream.read()) != -1) { 28 targetFileOutputStream.write(content); 29 } 30 31 }catch (FileNotFoundException e) { 32 e.printStackTrace(); 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } 36 } 37 }
比之前关闭流方式更简单,同时代码量也大大减少.
反编译
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.junit.Test; public class NewFileCopyTest { public NewFileCopyTest() { } @Test public void copyFile() { String originalUrl = "lib/NewFileCopyTest.java"; String targetUrl = "targetTest/new.txt"; try { FileInputStream originalFileInputStream = new FileInputStream(originalUrl); Throwable var4 = null; try { FileOutputStream targetFileOutputStream = new FileOutputStream(targetUrl); Throwable var6 = null; try { int content; try { while((content = originalFileInputStream.read()) != -1) { targetFileOutputStream.write(content); } } catch (Throwable var33) { var6 = var33; throw var33; } } finally { if (targetFileOutputStream != null) { if (var6 != null) { try { targetFileOutputStream.close(); } catch (Throwable var32) { var6.addSuppressed(var32); } } else { targetFileOutputStream.close(); } } } } catch (Throwable var35) { var4 = var35; throw var35; } finally { if (originalFileInputStream != null) { if (var4 != null) { try { originalFileInputStream.close(); } catch (Throwable var31) { var4.addSuppressed(var31); } } else { originalFileInputStream.close(); } } } } catch (FileNotFoundException var37) { var37.printStackTrace(); } catch (IOException var38) { var38.printStackTrace(); } } }
可以看见反编译之后仍是之前关闭资源的方式,这就是一种语法糖.
特殊情况
资源对象被return的情况下,由调用方关闭
ByteArrayInputStream等不需要检查关闭的资源对象
使用socket获取的InputStream和OutputStream对象不需要关闭

浙公网安备 33010602011771号