返回对象的 getter 不允许调用者直接访问成员变量吗?

use*_*862 1 java oop

假设我有一个简单的类,它将用户的朋友存储在字符串的 ArrayList 中,并使用 getter 访问该 ArrayList:

public class User
{
  private ArrayList<String> mFriends;
  
  // ...other code like constructors and setters...

  public ArrayList<String> getFriends()
  {
    return mFriends;
  }
}
Run Code Online (Sandbox Code Playgroud)

由于 Java 和许多其他语言(等效地)是按引用传递的,这是否不允许 getFriends() 的调用者直接访问我的 ArrayList 字符串,即他们甚至可以在不调用我的 setter 的情况下修改它?

我觉得这极大地打破了封装的概念。除了动态创建一个具有相同值的新 ArrayList 并返回它之外,是否有正常的解决方法,或者我误解了什么?

编辑:我知道 Java 并不是真正的引用传递,而是传递原始对象地址的副本,但这与将对象暴露给类外的对象时传递引用的效果相同

Gio*_*uri 7

  1. Java没有,也从来没有实现过引用传递机制,它一直是按值传递
  2. 您所描述的问题称为Reference Escape,是的,您是对的,调用者可以修改您的对象,如果您通过reference公开它;
  3. 为了避免引用转义问题,您可以:
    1. 返回对象的深层副本(带有.clone());
    2. 使用现有数据创建一个新对象(例如new ArrayList<>(yourObjectHere));
    3. 或者想出一些其他的想法,也有其他一些方法可以做到这一点;
  4. 这并没有真正打破封装本身,这是相当如何实现封装正确设计的一个点;
  5. 您对性能的关注:不,它不会破坏性能,而且 - 它与性能无关;相反,它是OOP正确设计的问题,要求对象具有可变性不变性。如果你总是返回一个深拷贝而不是引用,你就没有机会很好地利用你的对象。
    举个例子:如果你想改变对象的状态而不只是通过它的 setter 设置一个新对象怎么办?如果你想修改现有的朋友(在你的例子中)怎么办?您认为创建一个新的朋友列表并将其设置到对象中会更好吗?不,在后一种情况下,您只是失去了对对象的控制。