5

首先,我将尝试解释这段代码背后的想法。我有一堆可以处理某种类型的其他类(Processables)的类(Processors)。我有一个处理器列表,可以按特定顺序执行它们。我有一个地图,它将检索我要为某个处理器处理(Processables)的数据。它看起来像这样。

public abstract class AbstractProcessable {
    ...
}

public class DummyProcessable extends AbstractProcessable {
   ...
}

public abstract class AbstractProcessor<T extends AbstractProcessable> {
    public abstract void process(List<T> listOfProcessables);
}

public class DummyProcessor extends AbstractProcessor<DummyProcessable> {

    @Override
    public void process(List<DummyProcessable> listToProcess) {
        ...
    }
}

到目前为止,这似乎工作正常。没有编译错误。但现在我有一个像下面这样的类:

public class RandomClass {

    private List<AbstractProcessor<? extends AbstractProcessable>> processors;

    private Map<Class<? extends AbstractProcessor>, List<? extends AbstractProcessable>> data;

    public RandomClass() {
        processors = new ArrayList<>();
        processors.add(new DummyProcessor());

        data = new HashMap<>();
        data.put(DummyProcessor.class, new ArrayList<DummyProcessable>());

        processAll();
    }

    private void processAll() {
        for (AbstractProcessor<? extends AbstractProcessable> processor : processors) {
            List<? extends AbstractProcessable> dataToProcess;
            dataToProcess = data.get(processor);
            processor.process(dataToProcess); // compile error
        }
    }
}

编译错误:

    The method process(List<capture#4-of ? extends AbstractProcessable>) in the type AbstractProcessor<capture#4-of ? extends AbstractProcessable> is not applicable for the arguments (List<capture#5-of ? extends AbstractProcessable>)

我知道它可能有点难以阅读,但我尽量简化它。我对泛型也不是很好,所以也许我用错了一些通配符?谁能帮我解决这个问题?

提前非常感谢!

4

3 回答 3

1

如果我正确理解你的问题,我前段时间问过一个类似的问题。简短的回答是您不能以您想要的方式使用这样的地图。好消息是你不需要它;)

问题是 Java 泛型是编译时的东西(你可能已经知道了),它们只存在于编译时,而不是你实际填充List. 你找不到用 Java 表达你的想法的方法,即使它看起来完全合法。

您可能会发现在某些情况下,超级类型标记对于提取参数很有用,并避免用户在合适的情况下提供显式参数(但请注意限制并考虑它们是否真的可以增加一些价值)。

简而言之,你最终会得到一个像

private Map<Class<?>, List<?>> data;

(或者您可以为此使用Guava 的Multimap实现),使用一些强制转换并喊出一些警告,并依靠您的程序逻辑来确保客户端代码的类型安全。我在我的代码中使用了这种方法,到目前为止它从未失败过。

这是我的代码。我认为这正是您的情况,只需将Subscriber<T>and替换Message为您的Processor<T>andProcessable

public class MessageBus {

    public enum Action {
        CREATE, REMOVE, UPDATE, DELETE;
    }

    private static Map<Class<?>, Set<Subscriber<?>>> subscriptions;

    static {
        subscriptions = new HashMap<Class<?>, Set<Subscriber<?>>>();
    }

    @SuppressWarnings("unchecked")
    public static <T> void publish(T message, Action action) {
        Set<Subscriber<?>> set = getSubscribersFor(message.getClass());

        if (set == null)
            return;

        for (Subscriber<?> subscriber: set) {
            ((Subscriber<T>) subscriber).onMessage(message, action);
        }
    }

    public static <T> void subscribe(Class<T> type, Subscriber<T> subscriber) {
        Set<Subscriber<?>> set = getSubscribersFor(type);

        if (set == null) {
            set = new HashSet<Subscriber<?>>();
            subscriptions.put(type, set);
        }

        set.add(subscriber);
    }

    public static <T> void unsuscribe(Class<T> type, Subscriber<T> subscriber) {
        Set<Subscriber<?>> set = getSubscribersFor(type);
        set.remove(subscriber);
    }

    private static Set<Subscriber<?>> getSubscribersFor(Class<?> topic) {
        return subscriptions.get(topic);
    }
}
于 2012-11-11T18:35:33.167 回答
1

我怀疑这里的问题是:

  1. ? extends AbstractProcessableprivate List<AbstractProcessor<? extends AbstractProcessable>> processors;
  2. ? extends AbstractProcessableList<? extends AbstractProcessable> dataToProcess;

不是同一类型。? extends AbstractProcessable表示 的未知子类AbstractProcessable,没有任何力量认为这两个未知数应该相同(这就是您收到错误的原因,因为 unknown: 与 unknown:capture#4-of ? 不同capture#5-of ?)。不确定您的用途,RandomClass但我会将其更改为 a<T extends AbstractProcessable>并用于T定义列表和地图。这样列表和地图将具有相同的类型。

于 2012-11-11T19:30:28.570 回答
0

对我来说,听起来您在其中导入了 2 个不同的 List 类。检查导入部分并确保

import java.util.List

在两者中(或您需要的任何列表类型)

就像第一个猜测一样,没有详细检查您的代码:)

于 2012-11-11T18:21:00.180 回答