Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Don';返回对象的getter是否允许调用者直接访问成员变量?_Java_Oop - Fatal编程技术网

Java Don';返回对象的getter是否允许调用者直接访问成员变量?

Java Don';返回对象的getter是否允许调用者直接访问成员变量?,java,oop,Java,Oop,假设我有一个简单的类,它将用户的好友存储在字符串的ArrayList中,并使用getter访问该ArrayList: public class User { private ArrayList<String> mFriends; // ...other code like constructors and setters... public ArrayList<String> getFriends() { return mFriends;

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

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

  public ArrayList<String> getFriends()
  {
    return mFriends;
  }
}
公共类用户
{
私人ArrayList mFriends;
//…其他代码,如构造函数和setter。。。
公共ArrayList getFriends()
{
回报朋友;
}
}
由于Java和许多其他语言(等价地)通过引用传递,这不允许getFriends()的调用者直接访问我的字符串数组列表,也就是说,他们甚至不需要调用我的setter就可以修改它吗

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


编辑:我知道Java不是真正的按引用传递,而是传递原始对象地址的副本,但这与向类外的对象公开对象时按引用传递具有相同的效果

如果您担心封装,则可以返回列表的副本,例如

public ArrayList<String> getFriends() {
    return new ArrayList<>(mFriends);
  }
public ArrayList getFriends(){
返回新的ArrayList(mFriends);
}

顺便说一句,Java并不是真正的按引用传递,它更多的是按值传递。

如果您担心封装,那么您可以返回列表的副本,例如

public ArrayList<String> getFriends() {
    return new ArrayList<>(mFriends);
  }
public ArrayList getFriends(){
返回新的ArrayList(mFriends);
}
顺便说一下,Java并不是真正的按引用传递,而是按值传递

  • Java是而不是,从来没有实现过按引用传递机制,它一直是按值传递的
  • 您描述的问题称为,是的,您是对的,调用方可以修改您的对象,如果您通过引用公开它
  • 为了避免引用转义问题,您可以:
  • 返回对象的深度副本(使用
    .clone()
  • 使用现有数据创建一个新对象(例如,
    newarraylist(yourObjectHere)
  • 或者想出一些其他的想法,也有一些其他的方法来做到这一点
  • 这并没有真正破坏封装,本质上,这是如何实现封装的一个正确设计点
  • 你对绩效的关注:不,它不会破坏绩效,而且——它与绩效无关;相反,这是一个OOP的正确设计问题,要求对象的可变性或不变性。如果总是返回深度副本而不是引用,那么就没有机会充分利用对象。
    举个例子:如果您想更改对象的状态,而不只是通过其setter设置一个新对象,该怎么办?如果您想修改现有的朋友(在您的示例中),该怎么办?您认为创建一个新的朋友列表并将其设置到对象中更好吗?不,在后一种情况下,您只是失去了对对象的控制
  • Java是而不是,从来没有实现过按引用传递机制,它一直是按值传递的
  • 您描述的问题称为,是的,您是对的,调用方可以修改您的对象,如果您通过引用公开它
  • 为了避免引用转义问题,您可以:
  • 返回对象的深度副本(使用
    .clone()
  • 使用现有数据创建一个新对象(例如,
    newarraylist(yourObjectHere)
  • 或者想出一些其他的想法,也有一些其他的方法来做到这一点
  • 这并没有真正破坏封装,本质上,这是如何实现封装的一个正确设计点
  • 你对绩效的关注:不,它不会破坏绩效,而且——它与绩效无关;相反,这是一个OOP的正确设计问题,要求对象的可变性或不变性。如果总是返回深度副本而不是引用,那么就没有机会充分利用对象。
    举个例子:如果您想更改对象的状态,而不只是通过其setter设置一个新对象,该怎么办?如果您想修改现有的朋友(在您的示例中),该怎么办?您认为创建一个新的朋友列表并将其设置到对象中更好吗?不,在后一种情况下,您只是失去了对对象的控制

  • 对于易变对象,您是正确的。你可以用这样的东西把这块地包起来。我们还看到,for(可变)集合没有getter,但是
    addFriend
    getFriend(index)
    等等

    事实上,getter(特别是setter)已不再是一种备受推崇的模式


    成员“m”前缀更适合于其他语言。

    您适合可变对象。你可以用这样的东西把这块地包起来。我们还看到,for(可变)集合没有getter,但是
    addFriend
    getFriend(index)
    等等

    事实上,getter(特别是setter)已不再是一种备受推崇的模式


    成员“m”前缀更适合于其他语言。

    这里您要防止的是外部代码修改,
    ArrayList
    mFriends
    引用的。但是正如您所注意到的,外部代码仍然可以修改该列表的内容。如果您想避免这种情况,您可以使用
    Collections.unmodifiableList
    ,或者返回一份副本。是的,这正是我的意思。对于将非内置的“标准”Java对象传回,这将如何工作?例如,我应该信任用户在不使用setter的情况下不修改其内容吗?如果他们不修改内容很重要,那么