IO流释放资源的方式
一、使用close()方法释放资源的不足之处
二、优化方案
1、try-catch-finally
- finally:在异常处理时提供
finally块
来执行所有清除操作,比如:IO流中的释放资源。 - 特点:被finally控制的语句最终一定会执行,除非JVM退出。
- 异常处理标准格式:try…catch…finally。
package com.app.d6_release_resource;
import java.io.*;
/**
目标:学会使用finally释放资源
finally:无论程序是正常结束,还是出现异常,都要执行finally块的代码
*/
public class TryCatchFinallyDemo01 {
public static void main(String[] args) {
// 注意:要想使用finally执行IO流的代码,就需要将管道创建在外面
// 1、定义一个文件字节输入流
InputStream is = null;
// 2、定义一个文件字节输出流
OutputStream os = null;
try {
// System.out.println( 10 / 0 ); // 创建管道之前出现异常!!
// 1、创建一个文件字节输入流管道与源文件接通
is = new FileInputStream("day10-file-io-app/src/out03.txt");
// 2、创建一个文件字节输出流管道与目标文件接通
os = new FileOutputStream("day10-file-io-app/src/out04.txt");
// 3、读写数据,拷贝视频
// 定义一个字节数组存储原视频数据
byte[] buffer = new byte[1024]; // 1KB
int len; // 记录每次读取的字节数。(为了防止数据会多倒出)
// 定义一个循环,开始将原视频数据拷贝到目标路径下
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len); // 读取多少倒出多少(保证数据的完整性)
}
System.out.println("拷贝完成~~");
System.out.println( 10 / 0 ); // 关闭流之前出现异常!!
return; // 关闭流之前结束main方法!!
} catch (Exception e) {
e.printStackTrace();
} finally {
// 无论程序是正常结束,还是出现异常,都要执行这里的代码
System.out.println("-------finally块代码被执行了--------");
try {
// 4、关闭流
// 注意:关闭前,必须判断一下流是否为null(因为实际开发中会有很多代码,为了防止在创建管道前就出现了异常,判断一下是好事!)
if (os != null) os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (is != null) is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
拷贝完成~~
-------finally块代码被执行了--------
java.lang.ArithmeticException: / by zero
at com.app.d6_release_resource.TryCatchFinallyDemo01.main(TryCatchFinallyDemo01.java:38)
Process finished with exit code 0
2、面试题可能会出现
package com.app.d6_release_resource;
/**
扩展:面试题可能会出现
*/
public class TryCatchFinallyDemo02 {
public static void main(String[] args) {
// 计算10乘以2的结果
System.out.println(test(10, 2));
}
public static int test(int a, int b) {
try {
int c = a / b;
return c;
}catch (Exception e) {
e.printStackTrace();
return -1; // 计算结果出现bug,返回-1
}finally {
// 哪怕上面有 return语句的执行,也必须先执行完这里的代码才可以!
// 开发中不建议在这里加 return,因为加了,返回的永远是这里的数据了,这样会出现问题!!
return 100;
}
}
}
100
Process finished with exit code 0
总结
1、try…catch…finally的作用是啥?
- finally代码块是最终一定要执行的,可以在代码执行完毕的最后用于释放资源比较好!!
3、try-with-resource
- finally虽然可以用于释放资源,但是释放资源的代码过于繁琐?
- 有没有办法简化?
(1)JDK7 和 JDK9 中都简化了资源释放操作
(2)注意
JDK7
以及JDK9
的()
中只能放置资源对象,否则报错!!- 什么是资源呢?
- 资源都是实现了
Closeable/AutoCloseable
接口的类对象。
public abstract class InputStream implements Closeable {}
public abstract class OutputStream implements Closeable, Flushable {}
package com.app.d6_release_resource;
import java.io.*;
/**
目标:学会使用JDK7的try...catch...resource自动释放资源:推荐使用!
*/
public class TryCatchResourceDemo03 {
public static void main(String[] args) {
try (
// 1、创建一个文件字节输入流管道与源文件接通
InputStream is = new FileInputStream("day10-file-io-app/src/out03.txt");
// 2、创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("day10-file-io-app/src/out04.txt");
// int a = 123; // 报错!!因为这里只能放置资源
MyConnection connection = new MyConnection(); // 最终会自动调用资源的close()方法
) {
// 3、读写数据,拷贝视频
// 定义一个字节数组存储原视频数据
byte[] buffer = new byte[1024]; // 1KB
int len; // 记录每次读取的字节数。(为了防止数据会多倒出)
// 定义一个循环,开始将原视频数据拷贝到目标路径下
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len); // 读取多少倒出多少(保证数据的完整性)
}
System.out.println("拷贝完成~~");
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
模拟一个连接资源
*/
class MyConnection implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("连接资源被释放了!!");
}
}
拷贝完成~~
连接资源被释放了!!
Process finished with exit code 0
(3)JDK9资源释放操作
- 不建议这种操作!!
package com.app.d6_release_resource;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/**
目标:学会使用JDK9的try...catch...resource自动释放资源:可以了解一下。
*/
public class TryCatchResourceDemo04 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输入流管道与源文件接通
InputStream is = new FileInputStream("day10-file-io-app/src/out03.txt");
// 2、创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("day10-file-io-app/src/out04.txt");
try ( is; os ) {
// 3、读写数据,拷贝视频
// 定义一个字节数组存储原视频数据
byte[] buffer = new byte[1024]; // 1KB
int len; // 记录每次读取的字节数。(为了防止数据会多倒出)
// 定义一个循环,开始将原视频数据拷贝到目标路径下
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len); // 读取多少倒出多少(保证数据的完整性)
}
System.out.println("拷贝完成~~");
} catch (Exception e) {
e.printStackTrace();
}
}
}
拷贝完成~~
Process finished with exit code 0
总结
1、try…catch…resource的作用是啥?
- 自动释放资源、代码简洁。