不灭的焱

革命尚未成功,同志仍须努力下载JDK17

作者:Albert.Wen  添加时间:2021-08-01 17:28:15  修改时间:2024-04-20 23:34:23  分类:Java框架/系统  编辑

我们在使用资源的时候,必须关闭资源,比如使用jdbc连接或者inputStream的时候,必须在finally中将资源关闭。然而有的时候我们会忘记关闭资源。那么有没有更好的方法呢?

SqlSession sqlSession = sqlSessionFactory.openSession()
try{
	//......
} finally {
	sqlSession.close();
}

从jdk1.7开始,   Java 7增强了try语句的功能——它允许在try关键字后跟一对圆括号,圆括号可以声明,初始化一个或多个资源,此处的资源指得是那些必须在程序结束时必须关闭的资源(比如数据库连接,网络连接等),try语句在该语句结束时自动关闭这些资源。这种称为try-with-resources语句

try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
	//......
}

像这样的话,执行完sqlsession会自动关闭,不用我们在finally中关闭,也再也不用担心忘记关闭了。

那么为什么这样可以自动关闭资源呢?是不是所有的资源都可以这样关闭呢?

实际上只要这些资源实现类实现了CloseableAutoCloseable接口,就可以自动关闭。比如Sqlsession它就是extends Closeable, Closeable extends AutoCloseable。

几乎所有的资源都可以用这种方式实现自动关闭资源,比如OutputStream,BufferedReader,PrintStream,InputStream等,都可以。据说到目前为止,只有JavaMail Transport对象不能利用这种方式实现自动关闭。

注意:如果try()里面有两个资源,用分号分开,资源的close方法的调用顺序与它们的创建顺序相反。

带有资源的try语句可以像一般的try语句一样具有catch和finally块。在try-with-resources语句中,任何catch或finally块都是在声明的资源被关闭后才会执行的。

举例说明:

/**
 * 关闭流测试
 * 通过读写文件进行测试
 */
public class ExceptionCloseTest {
	public static void main(String[] args) {
		copy();
	}

	/**
	 * 使用缓冲流完成文件的复制
	 */
	private static void copy() {
		//1.创建缓冲流
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try{
			//2.缓冲流的初始化
			bis = new BufferedInputStream(new FileInputStream("D:\\a\\七月上.mp3"));
			bos = new BufferedOutputStream(new FileOutputStream("D:\\a\\3.mp3"));
			byte bytes[] = new byte[2048];
			int len = 0;
			//3.读写操作
			while((len=bis.read(bytes))!=-1){
				bos.write(bytes,0,len);
			}
			bos.flush();
		}catch(Exception e){
			e.getStackTrace();
		}finally{
			/**
			 * 关闭流的操作 最麻烦写法
               对流逐个判断 如果流很多 要写很多个判断的方法
			 */
			if(bis!=null){
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(bos!=null){
				try {
					bos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

上面关流的方式不是很友好 我们可以根据流的特性写一个方法去关闭(改变在finally部分)

package com.fpy.exception;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
/**
 * 关闭流测试 通过读写文件进行测试
 */
public class ExceptionCloseTest {
	public static void main(String[] args) {
		copy();
	}
 
	/**
	 * 使用缓冲流完成文件的复制
	 */
	private static void copy() {
		// 1.创建缓冲流
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			// 2.缓冲流的初始化
			bis = new BufferedInputStream(new FileInputStream("D:\\a\\七月上.mp3"));
			bos = new BufferedOutputStream(new FileOutputStream("D:\\a\\3.mp3"));
			byte bytes[] = new byte[2048];
			int len = 0;
			// 3.读写操作
			while ((len = bis.read(bytes)) != -1) {
				bos.write(bytes, 0, len);
			}
			bos.flush();
		} catch (Exception e) {
			e.getStackTrace();
		} finally {
			//作为实参传入close()自定义方法
			close(bis);
			close(bos);
		}
	}
 
	/**
	 * 基本上所学的流都实现了Closeable 接口 
	 * 所以可以使用多态的知识进行简化操作
	 * @param clo 表面是Closeable类型 实际上传入的流是谁那么关闭的流就是谁
	 */
	private static void close(Closeable clo) {//多态
		if (clo != null) {
			try {
				clo.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

看到这里会发现 我们只需要一个方法即可完成关流的操作,那么还有没有更简单的方法呢?我自己不想手动去关流,能不能自动关流呢?

答案是可以的(改变在去掉finally部分)

package com.fpy.exception;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
/**
 * 关闭流测试 通过读写文件进行测试
 * 
 * @author Mr.Gao
 */
public class ExceptionCloseTest {
	public static void main(String[] args) {
		copy();
	}
	/**
	 * 使用缓冲流完成文件的复制
	 */
	private static void copy() {
		// 1.创建缓冲流
		/**
		 * 使用java7的新特性 try(流的声明){
		 *   业务操作
		 * }catch(){};
		 * 不用再写关流的操作,内部自动完成资源的释放
		 * 
		 * 注意:没有   七月上1.mp3  资源
		 */
		try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\a\\七月上1.mp3"));
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\a\\3.mp3"));) {
			byte bytes[] = new byte[2048];
			int len = 0;
			// 3.读写操作
			while ((len = bis.read(bytes)) != -1) {
				bos.write(bytes, 0, len);
			}
			bos.flush();
			System.out.println("Suucess");
		} catch (FileNotFoundException e) {
			//e.printStackTrace();
			System.out.println(e.getMessage());
			
		} catch (IOException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}
}

运行效果:

 

 

参考:

java try(){}catch(){}自动资源释放(与传统写法举例对比)

java try()自动释放_try(){}自动释放资源,AutoCloseable