簡體   English   中英

Java 類型通配符

[英]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方法不適用。

有兩種可能的修復方法:

  1. 將簽名更改為notifyChange(ChangeHolder<? extends T> change)以便該方法適用於子類型。
  2. 擺脫無處不在的通配符,這樣你就只有<T>

我更喜歡解決方案 1,因為簽名盡可能通用是個好主意。

暫無
暫無

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

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