[英]How to use collections and generics with wildcards?
首先,我将尝试解释此代码背后的想法。 我有一堆类(处理器)可以处理某种类型的其他类(Processables)。 我有一个处理器列表以按特定顺序执行它们。 我有一个Map,它将检索我要为某个处理器处理的数据(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>)
我知道这可能有点难以阅读,但我试图尽可能地简化它。 我对泛型也不是那么好,所以也许我用了一些通配符错了? 任何人都可以帮我解决这个问题吗?
非常感谢提前!
如果我正确地理解你的问题,我前一段时间就问过类似的问题。 简短的回答是你不能以你想要的方式使用这样的地图。 好消息是你不需要它;)
问题是Java泛型是编译时的事情(正如您可能已经知道的那样),并且它们仅在编译时存在,而不是在您实际填充List
。 你无法找到用Java表达你的想法的方法,即使它看起来是完全合法的。
您可能会发现超级类型标记在某些情况下可用于提取参数,并避免用户在适当时提供显式参数(但请注意限制并考虑它们是否可以真正添加某些值)。
简而言之,你最终会得到像这样的领域
private Map<Class<?>, List<?>> data;
(或者你可以使用Guava的Multimap
实现),使用一些强制转换并喊出一些警告,并依靠你的程序逻辑使客户端代码是类型安全的。 我在我的代码中使用了这种方法,到目前为止它从未失败过。
这是我的代码。 我认为这正是您的情况,只需将Subscriber<T>
和Message
替换为您的Processor<T>
和Processable
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);
}
}
我怀疑这里的问题是:
? extends AbstractProcessable
从private List<AbstractProcessor<? extends AbstractProcessable>> processors;
? extends AbstractProcessable
private List<AbstractProcessor<? extends AbstractProcessable>> processors;
和 ? extends AbstractProcessable
从List<? extends AbstractProcessable> dataToProcess;
? extends AbstractProcessable
List<? extends AbstractProcessable> dataToProcess;
不是同一类型。 ? extends AbstractProcessable
? extends AbstractProcessable
代表一个未知的子类AbstractProcessable
,没什么力量,这两个未知的应该是相同的(这就是为什么你的错误,因为未知的: capture#4-of ?
是不同的,则未知: capture#5-of ?
)。 不确定您的RandomClass
的目的,但我会将其更改为<T extends AbstractProcessable>
并使用T
来定义列表和地图。 这样列表和地图将具有相同的类型。
对我来说,听起来你在这些中导入了2个不同的List类。 检查导入部分并确保
import java.util.List
是两个(或你需要的任何列表类型)
就像第一次猜测一样,没有详细检查你的代码:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.