java关闭资源,自制关闭资源工具类
在网上看到一篇关于关闭资源的正确方式:http://blog.csdn.net/bornforit/article/details/6896775
该博文中的总结:
(1)使用finally块来关闭物理资源(非托管资源),保证关闭操作始终会被执行;
(2)关闭每个资源之前首先保证引用该资源的引用变量不为null;
(3)为每个物理资源使用单独的trycatch块关闭资源,保证关闭资源时引发的异常不会影响其他资源的关闭。
在资源过多的时候,我们要在finally块中写很多的非空判断、以及try-catch块。如果没有关闭非托管资源,比如Connection,即使你给它赋值为null, 它也会常驻内存,必须要手动关闭非托管资源。不管是托管资源还是非托管资源,我们都希望能用相同的方式关闭。为了防止某些时候忘了给资源做非空判断、对每个资源都使用一个try-catch块关闭而导致资源/内存泄漏(), 我们自制一些关闭资源的工具类。而且使用工具类可以减少代码冗余、使代码可读性更好。
下面是我写的工具类:
CloseResources.java
public class CloseResources {
private static final Object[] PARAMS = new Object[0];//使用反射调用方法时传入的参数,可以当作null
private static final ExceptionHandle[] HANDLERS = new ExceptionHandle[0];//空的异常处理器,可以认为是null
private static boolean invokeCloseMethod(Object o, Method[] methods) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {//用反射执行无参的close()方法
for (Method method : methods) {
//System.out.println(method.getName());
if (method.getName().equals("close") && method.getParameterTypes().length == 0) {
System.out.println("############调用close() " + o.getClass());
method.invoke(o, PARAMS);
return true;
}
}
return false;
}
public static void close(Object o) {
close(o, null);
}
public static void close(Object o, ExceptionHandle handle) {//ExceptionHandle是我自己定义的
if (o == null) {//如果为空就不调用close()了,免得空指针异常
return;
}
Class<?> clazz = o.getClass();
try {
if (!invokeCloseMethod(o, clazz.getDeclaredMethods())) {//如果重写了close(),就调用重写的
invokeCloseMethod(o, clazz.getMethods());//如果没有重写close(),就调用继承的close()
}
} catch (SecurityException e) {
if (handle != null) {
handle.handleSecurityException(e);
}
} catch (IllegalAccessException e) {
if (handle != null) {
handle.handleIllegalAccessException(e);
}
} catch (IllegalArgumentException e) {
if (handle != null) {
handle.handleIllegalArgumentException(e);
}
} catch (InvocationTargetException e) {
if (handle != null) {
handle.handleInvocationTargetException(e);
}
} catch (Exception e) {
if (handle != null) {
handle.handleException(e);
}
}
}
public static void closeCollection(Collection<?> collection) {//关闭collection,比如List
closeCollection(collection, HANDLERS);
}
public static void closeCollection(Collection<?> collection, ExceptionHandle ... handles) {
if (collection == null) {
return;
}
int i = 0;
for (Object o : collection) {
if (handles == null) {
close(o);
} else if (i < handles.length) {
close(o, handles[i++]);
} else {
close(o);
}
}
collection.clear();
}
public static <K, V> void closeMap(Map<K, V> map) {//关闭map
closeMap(map, HANDLERS);
}
public static <K, V> void closeMap(Map<K, V> map, ExceptionHandle ... handles) {
if (map == null) {
return;
}
Set<K> keys = map.keySet();
int i = 0;
for (K key : keys) {
if (handles == null) {
close(map.get(key));
} else if (i < handles.length) {
close(map.get(key), handles[i++]);
} else {
close(map.get(key));
}
}
map.clear();
}
}
CloseResources工具类的几个方法:
public static void close(Object o):关闭o,不做任何处理
public static void close(Object o, ExceptionHandle handle): 用自定义处理异常的方式关闭o
public static void closeCollection(Collection<?> collection): 关闭collection中的所有资源,并清空collection
public static void closeCollection(Collection<?> collection, ExceptionHandle ... handles): 用自定义异常处理的方式分别关闭collection中的所有资源,并清空collection
putlic static <K, V> void closeMap(Map<K, V> map): 关闭map中的所有资源,并清空map
putlic static <K, V> void closeMap(Map<K, V> map, ExceptionHandle ... handles): 用自定义异常处理的方式分别关闭map中的所有资源,并清空map
如果资源o为null,那么CloseResources的close方法会直接返回,不做处理
使用CloseResources的close方法时还可以传入ExceptionHandle类来接受关闭资源时抛出的异常,并做处理
ExceptionHandle.java
public class ExceptionHandle {
public void handleSecurityException(SecurityException e) {}
public void handleIllegalAccessException(IllegalAccessException e) {}
public void handleIllegalArgumentException(IllegalArgumentException e) {}
public void handleInvocationTargetException(InvocationTargetException e) {}
public void handleException(Exception e) {}
}
MyResource.java:
我在close方法中强行抛出IOException,这样方便等会儿使用自定义异常处理的方式关闭资源
public class MyResource implements Closeable {
@Override
public void close() throws IOException {
throw new IOException("调用MyResource的close()时强行抛出IOException");
}
}
主类:
public class Main {
public static void main(String[] args) throws Exception {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
List<Object> list = new ArrayList<Object>();
try {
FileInputStream fis = new FileInputStream("c:/1.txt");
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(new FileOutputStream("c:/2.txt"));
list.add(bis);
list.add(bos);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
CloseResources.closeCollection(list);//可以关闭collection中的资源,并清空collection
CloseResources.close(new MyResource(), new ExceptionHandle() {
@Override
public void handleInvocationTargetException(InvocationTargetException e) {//使用自定义异常处理的方式关闭MyResource
System.out.println("ok");
Throwable t = e.getCause();
t.printStackTrace();
}
});
}
}
}
运行程序的结果:

在主方法中我写了这几句话:
@Override
public void handleInvocationTargetException(InvocationTargetException e) {
System.out.println("ok");
Throwable t = e.getCause();
t.printStackTrace();
}
可以看见,我打印的是InvocationTargetException的Cause,如果直接打印e,会包含InvocationTargetException的信息,实际上我们只需要close()抛出的IOException,因此我先获得Cause。如果不想用这种方式,而是直接把Cause: IOException传到handleException,不分出那么多的自定义异常处理方法,可以自己修改一下代码。在实际场景,不应该仅仅只调用printStackTrace(),而是把异常写入日志、尝试修复异常、做一些业务。
应该指出:这个工具类还很不完善,例如,只能执行资源无参的close()方法,还没有经过足够多的实际场景去验证它的性能、鲁棒性
java关闭资源,自制关闭资源工具类的更多相关文章
- java里poi操作excel的工具类(兼容各版本)
转: java里poi操作excel的工具类(兼容各版本) 下面是文件内具体内容,文件下载: import java.io.FileNotFoundException; import java.io. ...
- Java判断不为空的工具类总结
1.Java判断是否为空的工具类,可以直接使用.包含,String字符串,数组,集合等等. package com.bie.util; import java.util.Collection; imp ...
- Java字符串转16 进制工具类Hex.java
Java字符串转16 进制工具类Hex.java 学习了:https://blog.csdn.net/jia635/article/details/56678086 package com.strin ...
- Java中的AES加解密工具类:AESUtils
本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt; import com.mirana.frame.constants.SysConsta ...
- java.util.Arrays----操作数组的工具类
java.util.Arrays操作数组的工具类,里面定义了很多操作数组的方法 1.boolean equals(int[] a,int[] b):判断两个数组是否相等. 2.String toStr ...
- Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger
在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...
- Java学习笔记49(DBUtils工具类二)
上一篇文章是我们自己模拟的DBUtils工具类,其实有开发好的工具类 这里使用commons-dbutils-1.6.jar 事务的简单介绍: 在数据库中应用事务处理案例:转账案例 张三和李四都有有自 ...
- Java学习笔记48(DBUtils工具类一)
上一篇的例子可以明显看出,在增删改查的时候,很多的代码都是重复的, 那么,是否可以将增删改查封装成一个类,方便使用者 package demo; /* * 实现JDBC的工具类 * 定义方法,直接返回 ...
- java分页的实现(后台工具类和前台jsp页面)
1.首先,新建一个类Page.java public class Page implements Serializable { private static final long serialVers ...
- Java并发之Semaphore和Exchanger工具类简单介绍
一.Semaphore介绍 Semaphore意思为信号量,是用来控制同时访问特定资源的线程数数量.它的本质上其实也是一个共享锁.Semaphore可以用于做流量控制,特别是公用资源有限的应用场景.例 ...
随机推荐
- ASM磁盘组中的AU与条带
一.AU与条带(AU和条带就是一个分配单位,数据会被以一定单位分割,存储在多个磁盘中.分割单位的大小由AU.条带来决定. ASM有两种条带: 1.不可调粗粒度: 相当于ASM没有条带,或者说AU就是条 ...
- SpringCloud学习笔记(3)----Spring Cloud Netflix之深入理解Eureka
1. Eureka服务端的启动过程 1.1 入口类EurekaServerInitializerConfiguration类, public void start() { (new Thread(n ...
- layui层级
zIndex:layer.zIndex, success : function(layero){ var zIndex = layer.index; $(layero).css(‘z-index’,z ...
- luogu P4062 [Code+#1]Yazid 的新生舞会(线段树+套路)
今天原来是平安夜啊 感觉这题是道好题. 一个套路枚举权值\(x\),把权值等于\(x\)的设为1,不等于的设为-1,然后问题转化为多少个区间权值和大于. 发现并不是很好做,还有一个套路,用前缀和查分来 ...
- BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)
题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...
- 【BZOJ 1293】[SCOI2009]生日礼物
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 显然的滑动窗口题. (尺取法 如果l..i这一段已经有k种珍珠了. 那么就尝试把l++; (即把l这个影响尝试去掉一下 如果不足k种 ...
- hdoj 3376,2686 Matrix Again 【最小费用最大流】
题目:hdoj 3376 Matrix Again 题意:给出一个m*n的矩阵,然后从左上角到右下角走两次,每次仅仅能向右或者向下,出了末尾点其它仅仅能走一次,不能交叉,每次走到一个格子拿走这个格子中 ...
- 后缀自己主动机(SAM)学习指南
*在学习后缀自己主动机之前须要熟练掌握WA自己主动机.RE自己主动机与TLE自己主动机* 什么是后缀自己主动机 后缀自己主动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂 ...
- Fast Flux技术——本质就是跳板,控制多个机器,同一域名指向极多的IP(TTL修改为0),以逃避追踪
转自:http://ytuwlg.iteye.com/blog/355718 通过病毒邮件和欺诈网站学到的对付网络封锁的好东西:Fast Flux技术 收到一封邮件,引起我的好奇了: 邮件标题是:Ha ...
- 反弹木马——本质上就是一个开80端口的CS程序,伪造自己在浏览网页
反弹端口型木马分析了防火墙的特性后发现:防火墙对于连入的链接往往会进行非常严格的过滤,但是对于连出的链接却疏于防范.于是,与一般的木马相反,反弹端口型木马的服务端(被控制端)使用主动端口,客户端(控制 ...