繁体   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