Accessing private collection fields in Java

One of my classes has a field containing set This field is only populated in the constructor and then read by other classes At first I had this kind of thing:

public class Foo {
    public final Set<String> myItems;
    public Foo(Collection<String> theirItems) {
        this.myItems = new LinkedHashSet<String>(theirItems);
    }
}@H_301_12@ 
 

但这违背了OO最佳实践,myItems应该是私有的,并且只能通过setter和getter访问.所以我把它改成了:

public class Foo {
    private final Set<String> myItems;
    public Foo(Collection<String> theirItems) {
        this.myItems = new LinkedHashSet<String>(theirItems);
    }
    public Set<String> getItems() {
        return myItems;
    }
}@H_301_12@ 
 

现在myItems是私有的,但是调用getItems()的人仍然可以随意添加/删除项目,这与我之前的情况基本相同. (我实际上并不关心有人改变项目内容,这更像是一个理论问题)

所以我改变了getItems()来返回一个数组:

public String[] getItems() {
    return myItems.toArray(new String[myItems.size()]);
}@H_301_12@ 
 

现在我的物品真的很私密.不幸的是,我知道读取这些项目的对象实际上想要使用Set,因此必须将数组转换回来.我还可以返回myItems的副本:

public Set<String> getItems() {
    return new LinkedHashSet<String>(myItems);
}@H_301_12@ 
 

这为调用者提供了他们想要的内容,但在每次访问时都创建了一个新的Set.

在这样的情况下你做了什么 – 不惜一切代价保护隐私,接受原始结构的转换/复制,或者牺牲对集合内容的控制并依赖负责的呼叫者?

Solution

Return non modifiable views to your collection:

public Set<String> getItems() {
    return Collections.unmodifiableSet(myItems);
}@H_301_12@ 
 

请注意,这意味着如果调用者挂起到返回的集合,则仍会看到您对该集合所做的任何更改.如果你不想那样,你就得制作副本……没有(简单的)方法. (理论上,您可以制作一个不可修改的副本,并返回对同一副本的引用,直到您下次进行更改,但这会变得混乱.)

一个重点是记录您选择的任何内容,以便呼叫者不会得到任何令人讨厌的意外.在许多方面,我认为这实际上是大多数应用程序中最重要的事情,其中​​调用者实际上并不是恶意的.只要很清楚效果会是什么,在大多数情况下防守并不是那么重要.当然,如果您的来电者可能是一些不值得信任的代码,并且您的设置对于安全性等至关重要,那么您处于不同的情况.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>