例如,如果我有一个像这样的界面
public interface Partition<E> {
Set<E> getIncluded();
Set<E> getExcluded();
}
我是这样实现的
public class ImmutablePartition<E> implements Partition<E> {
private final ImmutableSet<E> included;
private final ImmutableSet<E> excluded;
ImmutablePartition(Set<E> included, Set<E> excluded) {
this.included = ImmutableSet.copyOf(included);
this.excluded = ImmutableSet.copyOf(excluded);
}
@Override
public Set<E> getIncluded() {
return included;
}
@Override
public Set<E> getExcluded() {
return excluded;
}
}
我真的实现了原始界面的精神吗?如果客户端代码得到 Set<E>
返回,尝试操纵它,并得到 UnsupportedOperationException
,这肯定违背了实现 Set<E>
的目的首先是界面吗?
这个问题适用于所有实现标准集合接口(interface)的 Guava Immutable* 集合 java.util
.
编辑:正如下面提醒我的那样,Collection
接口(interface)指定 UnsupportedOperationException
对于不支持的突变方法。我觉得期望仍然是返回的集合将允许修改,除非另有说明。如果我想返回一个不可变集合,如果可能的话,我会将返回类型指定为不可变类。
我想我的问题是:根据我的经验,通常的假设是返回的集合是可变的,那么实现返回通用集合并返回不可变集合的接口(interface)方法是否明智?
最佳答案
我不知道接口(interface)的精神是什么,但是Java集合接口(interface)的规范(又名Javadoc;-)明确指出不可变集合可以当用户尝试修改它们时抛出 UnsupportedOperationException
。
编辑以回答您编辑的问题
首先,我同意应该记录返回的集合是否可变。但是,我不同意默认假设是集合是可变的。此外,当返回的集合是可变的时,我希望记录这一点,并且记录当我修改集合时会发生什么(特别是:当我修改集合时,集合所源自的对象是否被修改,或者只是一些数据的副本)。
拥有诸如 ImmutableSet
、ImmutableList
等类型可能会很好,但 Java 标准库没有它们。原因是这种情况不是 boolean 值:集合可以部分修改,例如因为它允许删除元素但不允许添加新元素。为所有可能的组合提供单独的接口(interface)并不是一个好主意,因此 Java 设计者决定不采用任何接口(interface)。
您可以使用外部库,例如 Guava,但这也有缺点:
- 您引入了对外部库的依赖
- Guava 不可变集合包含原始数据的副本,而不是 View 。如果您的类只是想公开一些内部列表,而不希望调用者更改内部数据,那么每次都进行复制可能不是您想要的。
关于java - Guava Immutable* 类是否满足它们实现的标准集合接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35599336/