java - Java 中类型泛型的复杂案例

标签 java generics

我希望在 Java 中有一个类型以某种方式引用自身。

确切地说,我想要一个可以有监听器的命令类:

public abstract class GenericCommand<T> implements Future<T> {
    // ...
    private final List<GenericCommandListener<GenericCommand<T>>> listeners = new ArrayList<>();

    @SuppressWarnings("unchecked")
    public void addListeners(
            GenericCommandListener<GenericCommand<T>>... listeners) {
        this.listeners.addAll(Arrays.asList(listeners));
    }

    private void onValueAvailable() {
        for (GenericCommandListener<GenericCommand<T>> listener : listeners) {
            listener.onValueAvailable(this);
        }
    }
}

A GenericCommandListener看起来像

public interface GenericCommandListener<T extends GenericCommand<?>> {
    public void onValueAvailable(T theCmd);
}

此类命令的目的是发送到设备并产生某种类型的结果。

现在,我希望能够覆盖我的 GenericCommand<T>以便它执行一种特殊的命令,可能是 FooCommand ,它产生一个 Double :

public class QueryValueCommand extends GenericCommand<Double> {
}

现在,我创建了此类的实例并希望它接受 GenericCommandListener<QueryValueCommand> .但是我不能这样做;我所能做的就是让它接受 GenericCommandListener<GenericCommand<Double>> .

我看到了以下几种方式:

  1. ? super 做点什么或 ? extendsGenericCommand 的监听器定义中类(class)。我尝试了几种组合,但都没有奏效,因为对象无法放入列表中,或者调用不起作用。

  2. 更改 Listener 类的定义 - 但如何更改?

  3. 定义 GenericCommand以不同的方式进行分类,以便它始终使用对完全正确类型的监听器的引用:

    public abstract class GenericCommand<T> implements Future<T> {
        private final List<GenericCommandListener<MyExactTypeEvenIfSubclassing>> listeners = ...;
    }
    

    这样 QueryValueCommand从它派生接受 GenericCommandListener<QueryValueCommand> ?

最佳答案

正如 aruisdante 所提议的,GenericCommand 类必须以这种方式依赖于自身:

public abstract class GenericCommand<C extends GenericCommand<C, T>, T> implements Future<T> {
    // ...
    private final List<GenericCommandListener<C, T>> listeners = new ArrayList<>();

    @SuppressWarnings("unchecked")
    public void addListeners(
            GenericCommandListener<C, T>... listeners) {
        this.listeners.addAll(Arrays.asList(listeners));
    }

    private void onValueAvailable() {
        for (GenericCommandListener<C, T> listener : listeners) {
            listener.onValueAvailable((C) this);
        }
    }
}

监听器类也必须这样修改:

interface GenericCommandListener<C extends GenericCommand<C,T>, T>  {
    public void onValueAvailable(C theCmd);
}

现在,您可以声明:

public class QueryValueCommand extends GenericCommand<QueryValueCommand, Double>

你可以这样写:

QueryValueCommand command = new QueryValueCommand();
GenericCommandListener<QueryValueCommand, Double> listener = ...;

command.addListeners(listener);

关于java - Java 中类型泛型的复杂案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26343445/

相关文章:

java - MongoDB Spring 的日上限和下限

java - 函数式编程的 Number-Crushing 性能(使用 java 8)

java - 通用辅助方法与直接类转换?

swift - 了解常规版本和通用版本之间的函数调用优先级

Java 在具有两种类型的 Map 上使用泛型

java - 从对象中检索类名/实例

java - 如何使用单个数据库表在 adf 中创建树结构?

java - WebLogic openJDK 错误

java - MongoDB 使用聚合框架计算字段为 true 的次数

java - 什么是原始类型,为什么我们不应该使用它呢?