有关Ehcache的内容的引用和Java的deep copy
项目使用Ehcache来作为程序和数据库之间的缓冲, 使用过程中会对cache对象做修改, 如plan.setLangSymbol(),发现后面使用cache的地方,取到的数据都是修改后的,所以猜测是cache的浅引用造成的。
实际上,stackoverflow也有人提到此问题《Cache.get() returns deep copy of element?》
至于如何做deep copy,stackoverflow也提到《Copying cached Map<String , List> object into temporary Map<String , List> object》,经过实验,确认Guava的Maps.newHashMap(Map)工具类方法也是shallow copy。
一种方法就是循环对象内容,将每个属性赋值给重新构建的新对象。
另外有个更简单的方法,《A Java deep clone (deep copy) example》使用对象的序列化特性完成,看如下代码:
/** * This method makes a "deep clone" of any object it is given. */ public static Object deepClone(Object object) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(object); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return ois.readObject(); } catch (Exception e) { e.printStackTrace(); return null; } } } /** * These classes implement Serializable so we can write them out and * read them back in as a stream of bytes. */ class Person implements Serializable { String firstName, lastName; Address address; public Person(String firstName, String lastName, Address address) { this.firstName = firstName; this.lastName = lastName; this.address = address; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("First Name: " + firstName + "\n"); sb.append("Last Name: " + lastName + "\n"); sb.append("Street: " + address.street + "\n"); return sb.toString(); } }
很简单!