簡體   English   中英

Guava Immutable *類是否滿足它們實現的標准集合接口?

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

例如,如果我有一個類似的界面

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>接口的目的?

此問題適用於實現java.util標准集合接口的所有Guava Immutable *集合。

編輯:正如我在下面提醒的那樣, Collection接口為不支持的變異方法指定UnsupportedOperationException 除非另有說明,我覺得期望仍然是返回的集合將允許修改。 如果我想返回一個不可變集合,我會將返回類型指定為不可變類,如果可能的話。

我想我的問題是:通常的假設(根據我的經驗)是返回的集合是可變的,實現一個返回一般集合並返回一個不可變集合的接口方法是否合理?

我不知道接口的精神是什么,但Java集合接口的規范 (又名Javadoc ;-)清楚地表明,當用戶嘗試修改它們時,不可變集合可能會拋出UnsupportedOperationException

編輯以回答您編輯的問題

首先,我同意應該記錄返回的集合是否可變。 但是,我不同意默認的假設是該集合是可變的。 此外,當返回的集合是可變的時,我希望這是記錄的,並且還記錄了當我修改集合時會發生什么(特別是:當我修改集合時,集合來自哪個對象,或者它只是一些數據的副本)。

擁有像ImmutableSetImmutableList等類型可能會很好,但Java標准庫沒有它們。 原因是情況不是布爾值:集合可以是部分可修改的,例如因為它允許刪除元素但不允許添加新元素。 為所有可能的組合設置單獨的接口並不是一個好主意,因此Java設計者決定不使用任何接口。

您可以使用外部庫,例如Guava,但這也有缺點:

  • 您將依賴項引入外部庫
  • Guava不可變集合包含原始數據的副本,而不是視圖。 如果你的班級想要公開一些內部列表而沒有調用者更改內部數據的可能性,那么每次復制都可能不是你想要的。

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

是的

接口方法調用的行為是特定於實現的,直到文檔明確限制。 拋出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 e)您可以找到以下內容:

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

Arrays.asList()已經返回不允許add() List。

所以我認為返回不可修改或部分可修改的集合是可以的,判斷Java精神是由Java標准庫規范定義的。

使用ImmutableSet作為返回類型是完全有效的(在我看來,更好)。 人類讀者的線索是,他們所得到的將是不可改變的。

在我看來,它沒有。 我知道文檔聲明有可選操作,甚至這些方法也可能拋出UnsupportedOperationException (這是一個未經檢查的,因此調用者可能沒有准備好捕獲它),但我認為接口的目的是指定什么可以完成一個實現,並且由於這些方法存在於接口上,因此應該正確實現它們。 如果有可選操作,則應該有一些API通過代碼發現它,而不是通過閱讀文檔。

我甚至認為拋出UnsupportedOperationException違反了Liskov替換原則 毫無疑問,我不批評Guava,這是標准Java集合框架的一個問題,Guava的作者希望將不可變集合無縫集成到它中,並且他們必須做出一些妥協。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM