概述
java的Closeable和Cloneable两个接口,一字之差,但是要完成的功能却基本没有什么联系。最大的相同点在于,这两个就是java基本类库有特殊处理的接口,不按规则来,加班两行泪。
Closeable接口
概念
Closeable是可以关闭的数据源或目标。调用close方法可释放对象保存的资源(如打开文件)。
原理
这个实现是靠规则来保证的。实现类必须保证需要有资源释放,并且调用close接口可以实现资源的释放。
应用
在网上看到很多OkHttp来进行http请求的例子,里面的Response都没调用close方法进行关闭。将例子拷贝下来压测发现,会偶尔出现下面的告警:
[WARN] OkHttp ConnectionPool OkHttpClient A connection to XXX was leaked. Did you forget to close a response body? To see where this was allocated, set the OkHttpClient logger level to FINE: Logger.getLogger(OkHttpClient.class.getName()).setLevel(Level.FINE);
并且部分请求没有得到响应。
调整程序,实用try-with-resource方法关闭连接后,问题解决。这就是典型的资源没释放引起问题的例子。
在JDK1.7之后,只要实现了AutoCloseable或者Closeable接口的类或接口,都可以使用try-with-resource来实现异常处理和资源关闭。这种方法比手动在try外面定义资源,finally里调用close手动关闭资源代码更优雅。
Cloneable接口
概念
Cloneable接口是一个标记接口,里面没有定义任何内容。主要是和Object的clone方法配合使用。如果没有实现这个接口,而调用了clone方法,会抛出CloneNotSupportException。
原理
这个方法是为了弥补Object的clone方法缺陷。Object默认是浅拷贝。也就是说它并不会把对象的所有属性拷贝一份,而是有选择性的拷贝。拷贝规则如下:
1.基本类型,值拷贝。2.字符串类型,生成新对象,类似值拷贝。3.对象,地址引用拷贝。这样做的优点是节约内存。但是为了确保用户使用的时候,是了解自己用的什么拷贝,必须实现Cloneable接口。
应用
很多时候,我们需要实现深拷贝,比如需要每一份拷贝都对值做一定修改。这样深拷贝可避免对原值造成影响。
实现深拷贝,从代码上有两个比较简单的方法。一个是利用序列化和反序列化SerializationUtils.clone方法。还可以用apache的common包中的BeanUtils. copyProperties来实现。