简体   繁体   English

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

[英]Do the Guava Immutable* classes satisfy the standard collection interfaces they implement?

For instance, if I have an interface like 例如,如果我有一个类似的界面

public interface Partition<E> {
    Set<E> getIncluded();
    Set<E> getExcluded();
}

And I implement it like so 我这样实现它

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;
    }
}

Am I really implementing the spirit of the original interface? 我真的实现了原始界面的精神吗? If client code gets a Set<E> back, tries to manipulate it, and gets an UnsupportedOperationException , surely that defeats the purpose of implementing the Set<E> interface in the first place? 如果客户端代码返回Set<E> ,尝试操作它,并获得UnsupportedOperationException ,这肯定会破坏首先实现Set<E>接口的目的?

This question applies to all Guava Immutable* collections that implement the standard collection interfaces from java.util . 此问题适用于实现java.util标准集合接口的所有Guava Immutable *集合。

edit: As I've been reminded below, the Collection interface specifies the UnsupportedOperationException for unsupported mutation methods. 编辑:正如我在下面提醒的那样, Collection接口为不支持的变异方法指定UnsupportedOperationException I feel like the expectation still is that a returned collection will allow modification, unless otherwise stated. 除非另有说明,我觉得期望仍然是返回的集合将允许修改。 If I wanted to return an immutable collection, I would specify the return type as the immutable class, if possible. 如果我想返回一个不可变集合,我会将返回类型指定为不可变类,如果可能的话。

I guess my question is: being that the usual assumption (in my experience) is that a returned collection will be mutable, is it sensible to implement a interface method that returns a general collection and return an immutable collection? 我想我的问题是:通常的假设(根据我的经验)是返回的集合是可变的,实现一个返回一般集合并返回一个不可变集合的接口方法是否合理?

I don't know what the spirit of an interface is, but the specification (aka Javadoc ;-) of the Java collection interfaces clearly state that immutable collections may throw an UnsupportedOperationException when the user tries to modify them. 我不知道接口的精神是什么,但Java集合接口的规范 (又名Javadoc ;-)清楚地表明,当用户尝试修改它们时,不可变集合可能会抛出UnsupportedOperationException

Edit to also answer your edited question 编辑以回答您编辑的问题

First, I agree that whether a returned collection is mutable should be documented. 首先,我同意应该记录返回的集合是否可变。 However, I disagree that the default assumption is that the collection is mutable. 但是,我不同意默认的假设是该集合是可变的。 Also when a returned collection is mutable I expect that this is documented, and also that it is documented what happens when I modify the collection (in particular: is the object from which the collection originates modified when I modify the collection, or is it just a copy of some data). 此外,当返回的集合是可变的时,我希望这是记录的,并且还记录了当我修改集合时会发生什么(特别是:当我修改集合时,集合来自哪个对象,或者它只是一些数据的副本)。

It would maybe be good to have types like ImmutableSet , ImmutableList , and so on, but the Java standard library doesn't have them. 拥有像ImmutableSetImmutableList等类型可能会很好,但Java标准库没有它们。 The reason is that the situation is not a boolean: a collection can be partially modifiable, for example because it allows deleting elements but not adding new ones. 原因是情况不是布尔值:集合可以是部分可修改的,例如因为它允许删除元素但不允许添加新元素。 It would not be a good idea to have seperate interfaces for all possible combinations, and therefore the Java designers decided to have none. 为所有可能的组合设置单独的接口并不是一个好主意,因此Java设计者决定不使用任何接口。

You can use an external library, such as Guava, but this also has disadvantages: 您可以使用外部库,例如Guava,但这也有缺点:

  • You introduce a dependency to an external library 您将依赖项引入外部库
  • The Guava immutable collections contain a copy of the original data, not a view. Guava不可变集合包含原始数据的副本,而不是视图。 If your class just wants to make some internal list public without the possibility that the caller changes the internal data, making a copy every time is probably not what you want. 如果你的班级想要公开一些内部列表而没有调用者更改内部数据的可能性,那么每次复制都可能不是你想要的。

Do the Guava Immutable* classes satisfy the standard collection interfaces they implement?

YES . 是的

Behavior of interface method invocation is implementation specific, until explicitly restricted by documentation. 接口方法调用的行为是特定于实现的,直到文档明确限制。 Throwing UnsupportedOperationException is not violation of interface contract. 抛出UnsupportedOperationException不违反接口契约。

Example : 示例:

java.util.Collections.UnmodifiableList , which implements java.util.List do following: 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();
}

If you check javadoc of particular methods of List interface eg, boolean add(E e) you can find following: 如果检查List接口的特定方法的javadoc,例如boolean add(E e)您可以找到以下内容:

  throws UnsupportedOperationException if the add operation is not supported by this list 

Arrays.asList() already returns List that does not permit add() . Arrays.asList()已经返回不允许add() List。

So I guess returning non-modifiable or partially-modifiable collections are OK, judging that Java spirit is defined by Java standard library specification. 所以我认为返回不可修改或部分可修改的集合是可以的,判断Java精神是由Java标准库规范定义的。

It's perfectly valid (and in my view, preferable) to use ImmutableSet as the return type. 使用ImmutableSet作为返回类型是完全有效的(在我看来,更好)。 That clues in human readers that what they're getting will be immutable. 人类读者的线索是,他们所得到的将是不可改变的。

In my opinion it doesn't. 在我看来,它没有。 I know that the documentation states that there are optional operations, and even these methods may throw UnsupportedOperationException (which is an unchecked one so the caller might not be prepared for catching it), but I think the purpose of an interface is specifying of what can be done with an implementation, and since those methods are present on the interface, they should be properly implemented. 我知道文档声明有可选操作,甚至这些方法也可能抛出UnsupportedOperationException (这是一个未经检查的,因此调用者可能没有准备好捕获它),但我认为接口的目的是指定什么可以完成一个实现,并且由于这些方法存在于接口上,因此应该正确实现它们。 If there are optional operations then there should be some API to discover it by code, not by reading the documentations. 如果有可选操作,则应该有一些API通过代码发现它,而不是通过阅读文档。

I even think that throwing an UnsupportedOperationException is violating the Liskov substitution principle . 我甚至认为抛出UnsupportedOperationException违反了Liskov替换原则 Make no mistake, I don't criticize Guava here, this is rather a problem with the standard Java collection framework, the authors of Guava wanted to seamlessly integrate the immutable collections into it and they had to make some compromise. 毫无疑问,我不批评Guava,这是标准Java集合框架的一个问题,Guava的作者希望将不可变集合无缝集成到它中,并且他们必须做出一些妥协。

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

相关问题 杰克逊JSON,不可变类和接口 - Jackson JSON, Immutable Classes, and Interfaces 最佳实践:如何判断集合/ set / let是否是Guava ImmutableSet / Immutable映射? - Best practice: how do I tell if a collection/set/let is a Guava ImmutableSet/Immutable map? 是否有任何Java标准类在没有实现Collection的情况下实现Iterable? - Are there any Java standard classes that implement Iterable without implementing Collection? 您(几乎)总是在类中实现哪些方法和接口? - What methods and interfaces do you (almost) always implement in classes? 如何创建实现两个通用接口(不修改这些类)的许多类的实例的集合/列表? - How to create a collection/list of instances of many classes which implement two common interfaces (without modifying those classes)? 使用guava immutable集合作为方法参数和/或返回类型 - Use of guava immutable collection as method parameter and/or return type 从垃圾收集的角度看 Java 不可变类 - Java immutable classes from perspective of garbage collection 您如何使用Protostuff序列化Guava的不可变集合? - How do you serialize Guava's immutable collections using Protostuff? 番石榴一成不变的收藏品的缺陷? - Defects of Immutable collections of Guava? Guava Immutable版本的LinkedHashMultimap? - Guava Immutable version of LinkedHashMultimap?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM