简体   繁体   English

返回对象引用的最佳实践

[英]Best Practice for Returning Object References

Consider this code snippet: 请考虑以下代码段:

class MyClass{
    private List myList;
    //...
    public List getList(){
        return myList;
    }
}

As Java passes object references by value, my understanding is that any object calling getList() will obtain a reference to myList , allowing it to modify myList despite it being private . 当Java通过值传递对象引用时,我的理解是任何调用getList()对象都将获得对myList的引用,允许它修改myList尽管它是private Is that correct? 那是对的吗?

And, if it is correct, should I be using 而且,如果它是正确的,我应该使用

return new LinkedList(myList);

to create a copy and pass back a reference to the copy, rather than the original, in order to prevent unauthorised access to the list referenced by myList ? 创建副本并传回对副本的引用,而不是原始副本,以防止未经授权访问myList引用的列表?

I do that. 我这样做。 Better yet, sometimes I return an unmodifiable copy using the Collections API. 更好的是,有时我使用Collections API返回一个不可修改的副本。

If you don't, your reference is not private. 如果您不这样做,您的参考不是私人的。 Anyone that has a reference can alter your private state. 任何有参考的人都可以改变您的私人状态。 Same holds true for any mutable reference (eg, Date). 对于任何可变引用(例如,Date)也是如此。

It depends on what you want. 这取决于你想要什么。

Do you want to expose the list and make it so people can edit it? 您是否要公开列表并将其设置为人们可以编辑它?

Or do you want to let people look at it, but not modify it? 或者你想让人们看一下,但不能修改它?

There is no right or wrong way in this case. 在这种情况下没有正确或错误的方式。 It just depends on your design needs. 这取决于您的设计需求。

There can be some cases when one would want to return the "raw" list to the caller. 在某些情况下,人们可能希望将“原始”列表返回给调用者。 But in general, i think that it is a bad practice as it breaks the encapsulation and therefore is against OO. 但总的来说,我认为这是一个不好的做法,因为它打破了封装,因此反对OO。 If you must return the "raw" list and not a copy then it should be explicitly clear to the users of MyClass. 如果您必须返回“原始”列表而不是副本,那么应该向MyClass的用户明确说明。

I think that the pattern of making fields private and providing accessors is simply meant for data encapsulation. 我认为将字段设为私有并提供访问器的模式仅用于数据封装。 If you want something to be truly private, don't give it accessor methods! 如果你想要真正私密的东西,不要给它访问方法! You can then write other methods that return immutable versions of your private data or copies thereof. 然后,您可以编写其他方法来返回私有数据的不可变版本或其副本。

Yes, and it has a name.. "Defensive copy". 是的,它有一个名字......“防御性副本”。 Copying at the receiving end is also recommended. 还建议在接收端进行复制。 As Tom has noted , behavior of the program is much easier to predict if the collection is immutable. 正如Tom所指出的 ,如果集合是不可变的,程序的行为就更容易预测。 So unless you have a very good reason, you should use an immutable collection. 所以除非你有充分的理由,否则你应该使用一个不可变的集合。

When Google Guava becomes part of the Java standard library (I totally think it should), this would probably become the preferred idiom: Google Guava成为Java标准库的一部分时(我完全认为应该这样),这可能会成为首选的习语:

return ImmutableList.copyOf(someList);

and

void (List someList){
    someList = ImmutableList.copyOf(someList);

This has an added bonus of performance, because the copyOf() method checks whether the collection is already an instance of immutable collection ( instanceof ImmutableList ) and if so, skips the copying. 这有额外的性能,因为copyOf()方法检查集合是否已经是不可变集合的实例( instanceof ImmutableList ),如果是,则跳过复制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM