2011-01-26 57 views
3

我正在研究一些代码,当对象中的某些内容发生变化时,我想检测这些代码。跟踪更改的最简单方法之一是保留对象的旧副本。但是,看起来像获取深图的副本可能很困难。下面是我的尝试:如何跟踪对象图的更改?

 

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

要跟踪列表的变化,您可以使用此开源库: http://www.fuin.org/utils4j/examples/track-list-changes.html – user1672934

回答

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 
2

根据您的具体要求是什么,这可能努力改变对象制定者

  1. 控制访问(即使用适当的封装)
  2. 添加修改阵列是字符串
  3. 数组每次调用setter或其他任何改变对象的方法,调用toString并存储结果

这很简单,但可能适合您的需求并具有以下优点:

  1. 您可以将它抽象为基类以供重用。
  2. 您可以测试字符串相等性,以便不记录不会更改任何内容的集合。 (将当前更改与修订数组中的最后一个元素进行比较)
  3. 您可能会非常喜欢并拥有'recordChanges'之类的属性,因此录制仅在true时发生(可能是默认设置)。通过这种方式,如果您要连续执行一组设置,则可以一次记录所有更改,而不是每个设置。 (即创建的startRecording和stopRecording方法,当你的startRecording记录当前的状态)

它具有以下额外的工作:

  1. 你将不得不实行了坚实的toString和hashCode虽然。无论如何你可能必须这样做

  2. 如果你连续调用一组套件,它可能会很慢,但是你可以用上面的建议3来缓解。

最后,如果你有真正看中的,你可以实现的四个Momento pattern的团伙。对于你需要的东西(因为它可以让你恢复到以前的状态),这可能是过度杀伤的,但仍然会很棒。

0

您正在比较ArrayList和相同ArrayList的副本而没有任何更改。无论副本是否很深,它们总是具有相同数量的元素。

是的,在这种情况下,ArrayList保存引用,如果您在ArrayList的构造函数中传递一个列表,它将不会创建新对象,而是它将具有与对象相同的引用。

0

您可以考虑使用Observer。您可以创建一个Observer类,在发生更改时由您的对象通知您。也许你可以保留旧的和新的价值。然后,您可以将观察者添加到要跟踪的每个对象。你可以阅读更多关于这个选项herehere

0

您只将指针复制到引用。 list和old.stuff都指向同一个对象。对列表所做的任何更改都会反映在old.stuff中,反之亦然。您想使用Collections.copy制作列表的副本。然后,对列表的任何更改都不会反映在old.stuff中的参考(对差异列表对象)中。有关更多详细信息,请参阅this answer

0

列表的跟踪变化可以用ChangeTrackingUniqueList做 - 它提供了像 “list.isChanged()” 方法, “list.getDeleted()”,“清单.getAdded()“,你甚至可以用”list.revert()“来恢复列表。但它不会检测列表中对象的更改。它仅检测列表本身是否通过添加,删除或替换对象而更改。