有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java标签一个泛型类型参数,以超级

为了说明我的棘手问题,需要一点解释,所以请耐心听我说

我正在为一个可观察模式设计极简界面,该模式在可观察类中使用管理ListenerHandles而不是removeListener(...)方法

这就是想法:

public interface ListenerHandle<T> {

    boolean isRemoved();
    void remove();

    Listener<T> managedListener();
    Observable<T> containingObservable();
}

public interface Observable<T> {

    T get();
    void set(T value);

    ListenerHandle<T> addListener(Listener<T> listener);
}

public interface Listener<T> {
    void onChange(ListenerHandle<T> handle, T value);
}

现在这一切都很好

但是如果我想Observable<T>接受更一般的Listener? super T的侦听器也会接受T(它是逆变的

因此,ListenerHandle需要区分从Observable获得的T和管理的ListenerT

public interface ListenerHandle<TL, TO> {
    // ...

    Listener<TL> managedListener();
    Observable<TO> containingObservable();
}

public interface Observable<TO> {
    // ...

    <TL> ListenerHandle<TL, TO> addListener(Listener<TL> listener);
}

public interface Listener<TL> {
    void onChange(ListenerHandle<TL, ? extends TL> handle, TL value);
}

尽管这些接口将被编译,但我们知道TL

    <TL> ListenerHandle<TL, TO> addListener(Listener<TL> listener);

它有点太泛化了,因为它现在可以是任何东西。然而,Observable应该只能接受期待TO或其超类型的侦听器:

    <TL super TO> ListenerHandle<TL, TO> addListener(Listener<TL> listener);

这将不起作用,因为super只能用于通配符。所以另一个选择是:

    ListenerHandle<? super TO, TO> addListener(Listener<? super TO> listener);

然而,在这种情况下,调用者将丢失返回的ListenerHandle? super TOlistener? super TO将是相同的信息:

Observable<Number> o = ...;
Listener<Object> l = ...;

// does not work, but should (since we know that we passed a Listener<Object>)
ListenerHandle<Object, Number> h = o.addListener(l);
// works but Object is now generalized to ? super Number
ListenerHandle<? super Number, Number> h2 = o.addListener(l);

l = h2.managedListener(); // fails because ? super Number is not (necessarily) Object

因此,我需要一种方法来指定一个以super为界的标记的类型参数,以证明参数的有界泛型类型与返回类型的有界泛型类型相同。我怎么能这么做


共 (1) 个答案

  1. # 1 楼答案

    不必为Listener类型添加泛型参数TL,您可以将其设置为Listener<? super T>

    public interface ListenerHandle<T> {
    
        boolean isRemoved();
        void remove();
    
        Listener<? super T> managedListener();
        Observable<T> containingObservable();
    }
    
    public interface Observable<T> {
    
        T get();
        void set(T value);
    
        ListenerHandle<T> addListener(Listener<? super T> listener);
    }
    
    public interface Listener<T> {
    
        <TO extends T> void onChange(ListenerHandle<TO> handle, TO value);
    //  or:
    //  void onChange(ListenerHandle<? extends T> handle, T value);
    }
    

    如果确实需要将TL参数添加到ListenerHandle,我认为唯一的方法是static method workaround

    public interface ListenerHandle<TL, TO extends TL> {
    
        boolean isRemoved();
        void remove();
    
        Listener<TL> managedListener();
        Observable<TO> containingObservable();
    }
    
    public interface Observable<TO> {
    
        TO get();
        void set(TO value);
    
    //  @Deprecated
        ListenerHandle<?, TO> addListener(Listener<? super TO> listener); // implies ListenerHandle<? super TO, TO>
    
        @SuppressWarnings("unchecked")
        static <TL, TO extends TL> ListenerHandle<TL, TO> addListener(Observable<TO> observer, Listener<TL> listener) {
            return (ListenerHandle<TL, TO>) observer.addListener(listener);
        }
    }
    
    public interface Listener<TL> {
    
        void onChange(ListenerHandle<TL, ?> handle, TL value); // implies ListenerHandle<TL, ? extends TL>
    }
    

    你必须记住永远不要直接调用obs.addListener(lis),而是使用Observable.addListener(obs, lis)。将其标记为@Deprecated会给您一个警告,但您也需要将其应用于所有重写方法