Java中可变对象的封装

我正在学习“Java SE 7程序员I和II学习指南”,我不明白下面的解释。

class Fortress{ private String name; private ArrayList list; Fortress() {list=new ArrayList; String getName{return name;} void addToList(int x){list.add(x);} ArrayList getList(){return list;} // line 1 } 

哪行代码打破了封装? 答案:第9行。“当封装像ArrayList这样的可变对象时,你的getter必须返回对该对象副本的引用,而不仅仅是对原始对象的引用”。

我没有理解解释或如何修改原始代码。

所以在getList()而不是

 return list; 

我们应该这样做吗?

 ArrayList list2=list; return list2; 

你会替换:

 return list; 

有:

 return new ArrayList(list); 

否则客户可以做…

 foo.getList().add(5); 

打破封装。

 we do this? ArrayList list2=list; return list2; 

不,它说的是对象的副本,而不是引用的副本。

 ArrayList list2= new ArrayList<>(); list2.addAll( list ); return list2; 

或者如指出的那样, ArrayList有一个复制构造函数,它将另一个列表中的所有元素添加到新列表中。 以上三行主要是为了明确正在做什么。

您可以使用复制构造函数

 return new ArrayList(list); 
 return list; 

将返回对您的私有ArrayList列表的引用,这是封装中断的地方。

 ArrayList list2=list; return list2; 

即使在这里,你只是将列表的引用传递给list2你可以尝试 –

 ArrayList list2 = new ArrayList(); list2.addAll(list);