Java Guava Immutable*类是否满足它们实现的标准集合接口?

Java Guava Immutable*类是否满足它们实现的标准集合接口?,java,collections,interface,guava,immutability,Java,Collections,Interface,Guava,Immutability,例如,如果我有一个像 public interface Partition<E> { Set<E> getIncluded(); Set<E> getExcluded(); } 公共接口分区{ 设置getIncluded(); 设置getExcluded(); } 我就是这样实现的 public class ImmutablePartition<E> implements Partition<E> { pri

例如,如果我有一个像

public interface Partition<E> {
    Set<E> getIncluded();
    Set<E> getExcluded();
}
公共接口分区{
设置getIncluded();
设置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;
    }
}
公共类ImmutablePartition实现分区{
包括私有最终免疫表集;
不包括私有最终免疫表集;
ImmutablePartition(包含集合,排除集合){
this.include=ImmutableSet.copyOf(包含);
this.excluded=ImmutableSet.copyOf(已排除);
}
@凌驾
公共集getIncluded(){
包括退货;
}
@凌驾
公共集getExcluded(){
不包括退货;
}
}
我真的实现了原始界面的精神吗?如果客户机代码得到一个
,试图对其进行操作,并得到一个
不支持的操作异常
,那么这肯定会首先破坏实现
接口的目的吗

这个问题适用于所有实现
java.util
标准集合接口的Guava Immutable*集合

编辑:正如下面提醒我的那样,
集合
接口为不支持的突变方法指定了
不支持操作异常
。我觉得期望仍然是返回的集合将允许修改,除非另有说明。如果我想返回一个不可变的集合,如果可能的话,我会将返回类型指定为不可变类

我想我的问题是:根据我的经验,通常的假设是返回的集合是可变的,那么实现一个接口方法来返回一个常规集合并返回一个不可变集合是否明智?

数组。asList()
已经返回了不允许添加的列表

因此,我想返回不可修改或部分可修改的集合是可以的,因为Java spirit是由Java标准库规范定义的。

我不知道接口的spirit是什么,但是规范(又称Javadoc;-)许多Java集合接口明确指出,当用户试图修改不可变集合时,不可变集合可能会抛出
UnsupportedOperationException

编辑以回答您编辑的问题

首先,我同意应该记录返回的集合是否可变。但是,我不同意默认假设集合是可变的。另外,当返回的集合是可变的时,我希望这会被记录下来,并且当我修改集合时会发生什么情况也会被记录下来(特别是:当我修改集合时,是从中生成集合的对象被修改了,还是它只是一些数据的副本)

ImmutableSet
ImmutableList
等类型可能会更好,但Java标准库没有这些类型。原因是这种情况不是布尔型的:集合可以部分修改,例如,因为它允许删除元素,但不允许添加新元素。为所有可能的组合使用单独的接口不是一个好主意,因此Java设计人员决定不使用任何接口

您可以使用外部库,如番石榴,但这也有缺点:

  • 将依赖项引入外部库
  • Guava immutable集合包含原始数据的副本,而不是视图。如果您的类只想公开一些内部列表,而不希望调用方更改内部数据,那么每次都复制可能不是您想要的

Guava Immutable*类是否满足它们实现的标准集合接口?

接口方法调用的行为是特定于实现的,直到文档明确限制为止。 抛出
UnsupportedOperationException
并不违反接口约定

例如:

java.util.Collections.UnmodifiableList
,它实现了
java.util.List
执行以下操作:

public void remove() {
    throw new UnsupportedOperationException();
}
public void set(E e) {
    throw new UnsupportedOperationException();
}
public void add(E e) {
    throw new UnsupportedOperationException();
}
如果您检查
List
接口的特定方法的javadoc,例如,
boolean add(E)
,您可以找到以下内容:

public void remove() {
    throw new UnsupportedOperationException();
}
public void set(E e) {
    throw new UnsupportedOperationException();
}
public void add(E e) {
    throw new UnsupportedOperationException();
}

使用ImmutableSet作为返回类型是完全有效的(在我看来,更可取)。这给人类读者提供了线索,即他们所得到的东西是不变的。

在我看来不是。我知道文档中说明有可选操作,即使这些方法也可能抛出
UnsupportedOperationException
(这是一个未经检查的方法,因此调用方可能不准备捕获它),但我认为接口的目的是指定可以用实现执行的操作,由于接口上存在这些方法,因此应该正确地实现它们。如果有可选的操作,那么应该有一些API通过代码来发现它,而不是通过阅读文档


我甚至认为抛出一个
不支持操作异常
违反了规则。毫无疑问,我这里没有批评Guava,这是标准Java集合框架的一个问题,Guava的作者希望无缝地将不可变集合集成到其中,他们不得不做出一些妥协。

FYI:java库也有使集合不可变的方法:@Ferrybig the
collections.unmodifiableSet()
和相关方法不会使集合不可变。相反,它们提供了原始集合的不可修改视图。任何对原始集合有引用的人都可以修改它,并且这些修改可以通过视图集合看到。根据我的经验,通常的假设是