如何使可变对象列表不可变

时间:2014-03-24 08:53:58

标签: java collections immutability

嗨我被问到这个面试问题,你有一个不可变类中的对象列表,该类是否真的可以修改,可以修改什么以及如何防止它。我给出了以下解决方案。

public final class A{
   final List<B> listOfB; // B is mutable

   public List<B> getListOfB(){
      return Collections.unmodifiableList(this.listOfB);
   }
}

现在他说,即使在获得getListOfB()之后,他也可以改变&#39; B&#39;实例,并希望我也避免这种情况。然后我说。

public List<B> getListOfB(){
   List<B> ret;
   for(B b: this.listOfB){
       ret.add(b.clone()); // basically make a deep copy of 'b' for return list
   }
   return ret;
} 

面试官没有回复任何说这是对或错的事。

这个解决方案肯定有效。但有没有更好的方法,我的方法非常笨拙,需要额外的内存。

PS:假设B不能成为不可变的。

1 个答案:

答案 0 :(得分:2)

假设B是接口或接口A的实现,您可以使用listOfB java.net.ProxyB来包装A的每个元素。 UnsupportedOperationException分别通过抛出listOfB拦截所有修改调用。

更详细,用java.net.Proxy包装的实例替换A的每个项目,实现listOfB。然后,每当有人抓取UnsupportedOperationException的项目时,他将获得包装的实例。每当有人在这样一个包裹的项目上调用一个setter时,拦截该调用并抛出一个Collections.unmodifiableXXX()。希望你知道我的意思。它基本上是listOfB的作用。如果您了解可能修改B项的状态的所有方法,则POJO不必是{{1}}。只需确保您的包装器通过抛出异常来替换所有修改方法。