15

在从 getter 方法返回之前,我经常使集合字段不可修改:

private List<X> _xs;
....
List<X> getXs(){
  return Collections.unmodifiableList(_xs);
}

但是如果上面的 X 本身就是一个列表,我想不出一种方便的方法:

private List<List<Y>> _yLists;
.....
List<List<Y>> getYLists() {
  return Collections.unmodifiableList(_yLists);
}

上面的问题当然是,虽然客户端不能修改列表列表,但它可以从嵌入列表中添加/删除 Y 对象。

有什么想法吗?

4

6 回答 6

7

我能想到的最好的方法是使用来自 Google Collections 的 ForwardingList。欢迎评论。

private static <T> List<List<T>> unmodifiableList2(final List<List<T>> input) {
    return Collections.unmodifiableList(new ForwardingList<List<T>>() {
        @Override protected List<List<T>> delegate() {
            return Collections.unmodifiableList(input);
        }
        @Override public List<T> get(int index) {
            return Collections.unmodifiableList(delegate().get(index));
        }
    });
}
于 2009-01-06T10:31:06.017 回答
3

不幸的是,没有简单的方法可以在 java 中获得深度 const-ness。您必须始终确保列表中的列表也是不可修改的,从而绕过它。

我也有兴趣知道任何优雅的解决方案。

于 2009-01-06T09:58:26.440 回答
2

clojure 集合(map、set、list、vector)都可以嵌套,默认情况下是不可变的。对于纯java,有这个库:

http://code.google.com/p/pcollections/

于 2012-03-20T19:34:18.550 回答
0

如果您查看 Collections.unmodifiable*(...) 方法的实现,您会发现它们只是包装了集合。以同样的方式做一个深层的实用程序应该是可行的。

这样做的缺点是它向集合访问添加了额外的方法调用,因此会影响性能。

于 2009-01-06T10:16:32.490 回答
0

如果您在这里的唯一目标是强制封装,经典的解决方案是使用 clone() 或类似方法返回不是对象内部状态的结构。这显然只有在所有对象都可以克隆并且复制的结构足够小的情况下才有效。

如果这是一个相当常用的数据结构,另一种选择是使访问它的 API 更具体,以便您对特定调用有更详细的控制。如上所述,编写自己的 List 实现是一种方法,但如果您可以将调用范围缩小到特定用例,则可以公开特定的访问 API,而不是 List 接口。

于 2009-01-06T14:07:37.297 回答
0

万一有人对此感兴趣,这是一个简单的解决方案:

    public List<List<Double>> toUnmodifiable(List<List<Double>> nestedList) {
        List<List<Double>> listWithUnmodifiableLists = new ArrayList<>();
            for (List<Double> list : nestedList) {              
                listWithUnmodifiableLists
                    .add(Collections.unmodifiableList(list));
            }
        return Collections.unmodifiableList(listWithUnmodifiableLists);
    }

例如,如果您想使用 getList() 方法公开列表,这可以用作解决方案,您可以返回:toUnmodifiable(mNestedList),其中 mNestedList 是类中的私有列表。

我个人发现在 Android 中实现用于解析 GSON 的类时这很有用,因为能够修改响应没有意义,在这种情况下是反序列化的 json,我使用此方法作为公开的一种方式带有吸气剂的列表,并确保列表不会被修改。

于 2017-07-12T13:34:39.600 回答