可变对象与不可变对象
最近写代码不小心出了一个问题。
public ResponseResult queryEntitiesForExport(HE entity) { List<? extends PE> all = getEntitiesForExport(entity); if (ListUtil.size(all) == 0) return resultClient.getFailResult(FailMessage.EXPORT_DATA_NOT_EXIST); List<? extends PE> newAll = deepCopy(all); relatedQueryForExport(newAll); return resultClient.getSuccessResult(newAll); }
这里面在进行导出时会使用一个子方法 relatedForExport来修改查出来的值。换句话说这个查出来的值有可能会被子方法给改掉。
而这个查出来的值实际上不会被持久化,但查询一般会做缓存,也就是说再一次请求时,查出来的值有可能是被篡改后的值。
这会导致查出来的数据很奇怪。
之所以会犯这种错误,主要是明确使用可变对象可能带来的问题。
1.不可变对象可以反复使用。这种对象是非常适合进行缓存的。
2.可变对象不可反复使用。在一段业务逻辑执行完毕后应被释放。这种对象一般不建议做缓存。
从编程角度上来讲,对一个对象的操作只有两种,一种是不改变对象的状态,另一种是可改变对象的状态。
在使用可改变对象状态的操作的时候,一定要注意所使用的对象生命周期。如果该对象在业务逻辑处理完毕后就不存在,自然不会有问题。
如果仍然存在,但仍需要改变对象状态,且没有必要对此次的修改进行持久化。则不能直接修改缓存中的对象,而是复制这个对象进行操作。