[英]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
。
編輯以回答您編輯的問題
首先,我同意應該記錄返回的集合是否可變。 但是,我不同意默認的假設是該集合是可變的。 此外,當返回的集合是可變的時,我希望這是記錄的,並且還記錄了當我修改集合時會發生什么(特別是:當我修改集合時,集合來自哪個對象,或者它只是一些數據的副本)。
擁有像ImmutableSet
, ImmutableList
等類型可能會很好,但Java標准庫沒有它們。 原因是情況不是布爾值:集合可以是部分可修改的,例如因為它允許刪除元素但不允許添加新元素。 為所有可能的組合設置單獨的接口並不是一個好主意,因此Java設計者決定不使用任何接口。
您可以使用外部庫,例如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.