Publication/Escape 和 Java 中的封装

Publication/Escape and Encapsulation in Java

我正在读"Java Concurrency in Practice"这本书,有一部分我不太明白。我知道是一本老书,可能是没有提到我的疑惑的原因。

在 "Sharing object" 章节中有一个名为“发布和逃逸”的部分:

Publishing an object means making it available to code outside of its current scope, such as by storing a reference to it where other code can find it, returning it from a nonprivate method, or passing it to a method in another class ...

An object that is published when it should not have been is said to have escaped.

还有一个例子:

class UnsafeStates
{
   private String[] states = new String []
   {"AK", "AL" ....};

   public String [] getStates(){return states;}
}

Publishing states in this way is problematic because any caller can modify its contents. In this case, the states array has escaped its intend scope, because what was supposed to be private state has been effectively made public.

并指定不永远不这样做。

我突然想到了封装的概念,基本上就是说要做到这一点。

我误解了这些概念还是什么?

问题是这个方法:

public String [] getStates(){return states;}

Return 你对 states 数组的引用。

即使你声明 states 为私有,但如果你通过 getStates() 方法获取它,你仍然可以修改 states 变量:

UnsafeStates us = new UnsafeStates();
String[] copyStates = us.getStates();
copyStates[0] = "You don't know"; // Here the change to `copyStates` also affect the `states` variable since they're both reference to the same array.

通常,对于对象和数组属性,您通常会return该属性的深层副本以防止修改内部属性。

例如:对于数组:

String[] copied = new String[states.length];
System.arraycopy(states, 0, copied, 0, states.length);
return copied;

对于列表:

return Collections.unmodifiableList(internalList);

对于对象:

return internalObject.clone(); // Require deep clone