[英]Java Type Wildcarding
(為了這篇文章的目的,讓我們把 java.util.Observable 放在一邊)
我正在嘗試使用泛型,然后是通配符類型。 目的是創建一個類型通用的可觀察緩存,並為觀察者提供增量。 這開始偏離軌道的地方是我希望允許使用比 Observable 中指定的更通用的觀察者,例如Observer<Object>
或一些其他常見的超類。
我已經得出結論,這對於我的用例來說過於復雜,但問題本身繼續困擾着我,因為我顯然不明白如何正確使用類型通配符。
因此,如果我們從一個簡單的觀察者界面開始:
public interface Observer<T> {
public void notifyChange(ChangeHolder<T> change);
}
和相關的 ChangeHolder,在完整的實現中,這會更復雜,提供添加/更新/刪除對象的列表,但這足以證明問題
public interface ChangeHolder<T> {
T getChange();
}
所以在定義了 Observer 之后,我嘗試實現 Observable 抽象類:
public abstract class Observable<T> {
private Set<Observer<? super T>> observers = new HashSet<>();
public void addObserver(Observer<? super T> obs){
observers.add(obs);
}
public void change(ChangeHolder<T> changes){
for(Observer<? super T> obs : observers){
obs.notifyChange(changes);
}
}
}
有了這個,我可以定義一些對象緩存,通過聲明class TreeCache extends ObservableCache<Tree>
,(從這一點開始,我將使用 Tree 作為示例類用作 T,假設它是一個簡單的 POJO僅從 Object 擴展)並在必要時將ChangeHolder<Tree>
對象傳遞給TreeCache.change()
。 不幸的是,編譯器不同意:
The method notifyChange(ChangeHolder<capture#2-of ? super T>) in the type Observer<capture#2-of ? super T> is not applicable for the arguments (ChangeHolder<T>)
這就是我的理解結束的地方。
如果沒有 ChangeHolder 類(如果我的 notifyChange 方法只是使用一個普通的 T),它就可以正常工作,因為將 Tree 傳遞給 Observer.notifyChange(Object) 是完全合法的。
我推斷我應該能夠對 ChangeHolder 做同樣的事情 - ChangeHolder<T>
應該以與T
滿足notifyChange(? super T)
相同的方式滿足notifyChange(ChangeHolder<? super T>)
notifyChange(? super T)
但顯然我誤解了什么?
簽名notifyChange(ChangeHolder<T> change)
沒有通配符。 因此,傳遞參數的泛型類型必須與Observer
實例的泛型類型完全匹配。
Observer<? super T>
Observer<? super T>
表示某種未知類型的Observer
,它是T
的超類型。 由於obs
的泛型類型可能與changes
的泛型類型不完全匹配,因此notifyChange
方法不適用。
有兩種可能的修復方法:
notifyChange(ChangeHolder<? extends T> change)
以便該方法適用於子類型。<T>
。我更喜歡解決方案 1,因為簽名盡可能通用是個好主意。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.