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对象不需要关闭

posted @ 2020-06-12 02:08  mingmingn  阅读(116)  评论(0)    收藏  举报