Java IO流 - 释放资源的方式

资源释放的方式

书接上文, 在上一篇文章我们做过一个文件拷贝的练习, 但是在联系中是有释放资源隐患的的, 例如在下面代码中, 在文件释放之前有许多行的逻辑代码; 如果这许多行的逻辑代码有报错, 导致程序不运行, 那么资源就得不到释放

public static void main(String[] args) {
    
    
    try {
    
    
        InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.pdf");
        OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/newtest.pdf");

        byte[] arr = inp.readAllBytes();
        oup.write(arr);
        System.out.println("复制成功!");
      
      	// 许多行的逻辑代码

        oup.close();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

try-catch-finally

为了解决隐患, 我们需要使用try-catch-finally对资源释放进行优化

finally:在异常处理时提供finally块来执行所有清除操作,比如说IO流中的释放资源

特点:被finally控制的语句最终一定会执行(除非JVM退出)

异常处理标准格式:try….catch…finally

try….catch…finally格式:

try {
    
    
  	FileOutputStream fos = new FileOutputStream("a.txt");
	  fos.write(97); 
		fos.close(); 
} catch (IOException e) {
    
    
  	e.printStackTrace();
} finally {
    
    
  
}

使用try….catch…finally优化文件拷贝代码

由于finally中无法访问到 inp和oup, 所以我们需要在外部定义变量将 inp和oup保存起来

public static void main(String[] args) {
    
    
    // 在外部保存为了finally中可以访问到
    InputStream inp = null;
    OutputStream oup = null;
  
    try {
    
    
        inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.pdf");
        oup = new FileOutputStream("/Users/chenyq/Documents/newtest.pdf");

        byte[] arr = inp.readAllBytes();
        oup.write(arr);
        System.out.println("复制成功!");

    } catch (IOException e) {
    
    
        e.printStackTrace();
    } finally {
    
     // finally中释放资源
        try {
    
    
            if (inp != null) {
    
     // 非空校验
                inp.close();
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        try {
    
    
            if (oup != null) {
    
     // 非空校验
                oup.close();
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }
}

try-catch-resource

finally虽然可以用于释放资源,但是释放资源的代码过于繁琐, 那么有没有办法可以简化呢?

在这里插入图片描述

JDK7和JDK9中都简化了资源释放操作

在这里插入图片描述

JDK7改进方案演示:

在括号中放置资源对象, 并且是只能放置资源对象, 用完会自动关闭: 自动调用资源对象的close方法关闭资源(即使出现异常也会做关闭的操作)

public static void main(String[] args) {
    
    
    try(
            InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.pdf");
      
            OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/newtest.pdf");
            ) {
    
    

        byte[] arr = inp.readAllBytes();
        oup.write(arr);
        System.out.println("复制成功!");

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

JDK9改进方案演示:

弊端: 在try外部定义输入输出流还需要再抛出异常

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.pdf");
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/newtest.pdf");
    try(inp; oup) {
    
    

        byte[] arr = inp.readAllBytes();
        oup.write(arr);
        System.out.println("复制成功!");

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

注意:

JDK 7 以及 JDK 9的()中只能放置资源对象,否则报错

什么是资源呢?

资源都是实现了Closeable / AutoCloseable接口的类对象

public abstract class InputStream implements Closeable {}

public abstract class OutputStream implements Closeable, Flushable{}

猜你喜欢

转载自blog.csdn.net/m0_71485750/article/details/127594217