Java中可变对象的封装性

6
我正在学习《Java SE 7程序员I和II学习指南》,但我不理解下面的解释。
class Fortress{
  private String name;
  private ArrayList<Integer> list;

  Fortress() {list=new ArrayList<Integer>;

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

哪些代码会破坏封装?答案是:第9行。"当封装一个可变对象(如ArrayList)时,getter方法必须返回该对象的副本引用,而不仅仅是原始对象的引用。"
我既不理解这个解释,也不知道如何修改原始代码。
因此,在getList()中,需要返回一个新的ArrayList实例,而不是原始实例的引用。

return list;

我们应该这样做吗?

ArrayList<Integer> list2=list;
return list2;
4个回答

11
你需要替换:
return list;

使用:

return new ArrayList<Integer>(list);
否则客户端可以执行...
foo.getList().add(5);

破坏封装性。


2
we do this?

ArrayList<Integer> list2=list;
return list2;

不,它是说对象的副本,而不是引用的副本。
ArrayList<Integer> list2= new ArrayList<>();
list2.addAll( list );
return list2;
ArrayList有一个复制构造函数,可以将另一个列表中的所有元素添加到新列表中。上述三行代码主要是为了清楚地说明正在进行的操作。

1
你可以使用复制构造函数。
return new ArrayList<Integer>(list);

0
return list;

将会返回对你的私有ArrayList列表的引用,这破坏了封装。

ArrayList<Integer> list2=list;
return list2;

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接