我正在处理一些代码,当对象中的某些内容发生变化时,我想要检测这些代码。跟踪更改的最简单方法之一是保留对象的旧副本。但是,看起来获得深度图的副本可能很困难。这是我试过的:
public class Old{
protected Old old;
protected List stuff;
//Needed for JUnit
public Old(){
}
public Old(List stuff){
this.stuff=stuff;
old=this;
}
public void add(){
stuff.add(2);
}
public void match(){
System.out.printf("old:%d\nnew:%d\n",old.getStuff().size(),stuff.size());
}
public List getStuff(){
return new ArrayList(stuff);
}
@Test
public void testOld(){
List list=new ArrayList();
list.add(1);
Old thing=new Old(list);
thing.add();
thing.match();
}
}
输出:
old:2 new:2
因此,默认情况下old=this
似乎不会创建深层副本。我真正想要的是跟踪对该列表的更改以及可能的对象图。还有其他一些简单的选择吗?
答案 0 :(得分:2)
根据您的具体要求,这可能有效
这很简单,但可能适合您的需求,并有以下优点:
它有以下额外的工作:
您必须实现一个可靠的toString和hashCode。无论如何你可能要做的事情
如果您连续调用一堆集合可能会很慢,但您可以通过上面的建议3来缓解这一点。
最后,如果你真的很喜欢,你可以实现四人帮Momento pattern。这对你所需要的东西来说可能有些过分(因为它可以让你恢复到以前的状态),但仍然会很棒。
答案 1 :(得分:0)
您正在将ArrayList与同一ArrayList的副本进行比较而不进行更改。无论副本是否很深,它们总是具有相同数量的元素。
是的,在这种情况下,ArrayList保存引用,如果在ArrayList的构造函数中传递一个列表,它将不会创建新对象,而是对对象具有相同的引用。
答案 2 :(得分:0)
您可以考虑使用观察者。您可以创建一个Observer类,当发生更改时,该类会被对象通知。也许你可以保留旧的和新的价值观。然后,您可以将观察者添加到要跟踪的每个对象。您可以详细了解此选项here和here。
答案 3 :(得分:0)
您只复制了指向引用的指针。 list和old.stuff都指向同一个对象。对列表所做的任何更改都将反映在old.stuff中,反之亦然。您想使用Collections.copy制作List的副本。然后对list的任何更改都不会反映在old.stuff中的引用(对于差异List对象)中。有关详细信息,请查看this answer。
答案 4 :(得分:0)
在人们指出旧的可能指向新的之后,我添加了一个复制构造函数,事情看起来好多了。
public class Old{
protected Old old;
protected List stuff;
//Needed for JUnit
public Old(){
}
//Here's my new copy constructor.
public Old(Old old){
this.stuff=new ArrayList(old.getStuff());
this.old=null;
}
public Old(List stuff){
this.stuff=stuff;
old=new Old(this);//Here I now call the copy constructor.
}
public void add(){
stuff.add(2);
}
public void match(){
System.out.printf("old:%d\nnew:%d\n",old.getStuff().size(),stuff.size());
}
public List getStuff(){
return new ArrayList(stuff);
}
@Test
public void testOld(){
List list=new ArrayList();
list.add(1);
Old thing=new Old(list);
thing.add();
thing.match();
}
}
输出:
old:1 new:2
答案 5 :(得分:0)
跟踪列表的更改可以使用ChangeTrackingUniqueList完成 - 它提供了诸如“list.isChanged()”,“list.getDeleted()”,“list.getAdded()”之类的方法,你甚至可以使用“list.revert()”恢复列表。但它没有检测到列表中对象的更改。它仅通过添加,删除或替换对象来检测列表本身是否已更改。