我只是在学习Java,但我一遍又一遍地遇到同样的问题
如何有效地恢复某个对象的旧状态?
public class Example {
MyObject myLargeObject;
public void someMethod(){
MyObject myLargeMyObjectRecovery = myLargeObject;
/**
* Update and change myLargeObject
*/
if(someCondition){
//revert to previous state of myLargeObject
myLargeObject = myLargeMyObjectRecovery;
}
}
}
以上是我希望代码工作的方式,但显然不会,因为myLargeObject和myLargeObjectRecovery是对同一个对象的引用。
一种解决方案是创建一个复制构造函数。这对于小对象来说很好,但是如果我有一个大对象(在我的项目中,对象是一个大的2D数组意味着我将不得不遍历所有条目),这种方式感觉不对。
这一定是Java中一个非常普遍的问题,其他人如何绕过它呢?
答案 0 :(得分:1)
如您所述,深层复制或可能是序列化。您可以存储序列化字符串,然后稍后从中重新构建对象。
答案 1 :(得分:0)
最佳解决方案取决于您是否对MyObject
实例进行了外部引用。
如果您仅使用myLargeObject
课程中的Example
,则可以使用
byte[]
必须为transient
)如果您可以访问来自外部的MyObject
实例 ,那么它会变得更有趣,您必须引入同步。
MyObject
上的所有方法必须为synchronized
(以避免不一致的阅读)synchronized void saveState()
方法保存您的状态(通过序列化或复制构造函数)(后者更好)synchronized void restoreState()
,在内部恢复您的状态(对于复制字段,您可以使用带有复制构造函数的公共代码片段)在所有情况下,建议关闭事务(某种commit()
),这意味着当你到达那里时,你可以删除已保存的状态。
此外,非常重要的是,如果您有基础数据结构,那么应该遍历整个结构。否则,您可能会遇到对象引用问题。
小心使用 JPA实体或任何外部管理的对象,这些方法中的任何一种都不太可能与它们一起使用。
答案 2 :(得分:0)
如果将对象分配给另一个对象,则jvm引用内存中的同一对象。因此,对象的更改将在引用的其他对象中。
MyObject myLargeMyObjectRecovery = myLargeObject;
代码中的内容相同。 myLargeMyObjectRecovery
和myLargeObject
在内存中引用相同的对象。
如果要精确复制任何对象,可以使用Object.clone()方法。此方法将复制对象并返回一个对象,该对象引用其字段及其valus与coppied对象相同的另一个对象。
由于克隆方法受到保护,因此无法直接访问它。您可以根据您的要求实现Prototype模式。
http://www.avajava.com/tutorials/lessons/prototype-pattern.html
public class MyObject{
//fields, getters, setters and other methods.
public MyObject doClone()
{
MyObject clonedObject = this.clone(); //you may need to override clone()depending on your requirements.
return clonedObject;
}
}
并在您的代码中调用它
MyObject myLargeMyObjectRecovery = myLargeObject.doClone();
答案 3 :(得分:0)
Memento Pattern解决了恢复到以前状态问题的设计问题。当您需要捕获对象的一个或多个状态并能够恢复它们时,此方法很有用。将其视为N步撤消操作,就像在文本编辑器中一样。
在模式中,您有一个有状态对象Originator
,它负责保存和恢复其状态的快照。状态本身保存在名为Memento
的包装类中,它存储在CareTaker
中并通过{{1}}访问。
在这种方法中,最简单的想法是深层复制对象。但是,这在性能和空间方面可能效率低下,因为您只存储整个对象而不是变更集。
某些对象持久性库提供事务和快照的实现。看一下Prevayler,它是java的对象持久性库和prevalent system pattern的实现。库以事务的形式捕获对象的更改并将它们存储在内存中。如果需要持久存储POJO,可以定期将对象的快照保存在磁盘上,并在需要时还原为它们。
您可以在此SO问题中找到有关序列化POJO的更多信息:Is there a object-change-tracking/versioning Java API out there?