try-with-resource使用,这个听说比传统资源关闭更好

1,478 阅读2分钟

为什么要手动关闭资源呢

开篇先说下 为什么要手动关闭资源呢

Java不是说有垃圾回收机制吗,为什么还需要手动关闭资源呢

解释:

    因为GC只管内存不管别的资源。假如有内存以外的其它资源依附在Java对
    上,如native 
    memory(DirectByteBuffer)、file(FileInputStream)之类,那当然自己
    关闭最合适。为了“避免”程序员忘了自己释放那些资源,Java提供了finaliz
    er、PhantomReference之类的机制来让程序员向GC注册“自动回调释放资源”
    的功能。但GC回调它们的时机不确定,所以只应该作为最后手段来使用,主
    要手段还是自己关闭最好

常见需要手动释放得物理资源

1、文件/流资源

2、套接字资源

3、数据库连接资源

物理资源可以不手动释放吗

1、资源长时间无效占用

2、超过最大限制后,将无资源可用

3、导致系统无法正常运行

步入正题,try-with-resource 与传统关闭 对比使用

package gom.gc.guoshicheng.lambda.resource;

import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * jdk7 之前得文件拷贝功能
 */
public class FileCopyTest {

    @Test
    public void copyFile() {
        /**
         * 1、创建输入/输入流
         * 2、执行文件拷贝,读取文件内容,写入到另一个文件中
         * 3、 **关闭文件流资源**
         */

        //定义输入路径和输出路径
        String originalUrl = "D:\\work\\source\\学习\\_996\\src\\test\\java\\gom\\gc\\guoshicheng\\lambda\\resource\\FileCopyTest.java";
        String targetUrl = "D:\\work\\source\\学习\\_996\\target\\FileCopyTeste.java";

        //声明文件输入流,文件输入流
        FileInputStream originalFileInputStream = null;
        FileOutputStream targetFileOutputStream = null;

        try {
            //实例化文件流对象
            originalFileInputStream =
                    new FileInputStream(originalUrl);

            targetFileOutputStream =
                    new FileOutputStream(targetUrl);

            //读取得字节信息
            int content;

            //迭代,读取/写入字节
            while ((content = originalFileInputStream.read()) != -1) {
                targetFileOutputStream.write(content);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            //关闭流资源
            if (targetFileOutputStream != null) {
                try {
                    targetFileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (originalFileInputStream != null) {
                try {
                    originalFileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


class NewFileCopyTest {

    @Test
    public void copyFile() {

        //先定义输入/输出路径
        String originalUrl = "D:\\work\\source\\学习\\_996\\src\\test\\java\\gom\\gc\\guoshicheng\\lambda\\resource\\FileCopyTest.java";
        String targetUrl = "D:\\work\\source\\学习\\_996\\target\\FileCopyTeste.java";

        try (

                //声明文件输入流,文件输入流
                FileInputStream originalFileInputStream = new FileInputStream(originalUrl);
                FileOutputStream targetFileOutputStream = new FileOutputStream(targetUrl);
        ) {

            //读取得字节信息
            int content;

            //迭代,读取/写入字节
            while ((content = originalFileInputStream.read()) != -1) {
                targetFileOutputStream.write(content);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

资源关闭特殊情况

1、资源对象被return的情况下,由调用方关闭

2、ByteArrayInputStream等不需要检查关闭的资源对象

3、使用Socket获取的InputStream和OutputStream对象不需要关闭,因为socket关闭的时候自然就关闭了

总结

最重要的一点,就是try-with-resource的使用,代码量减少了