noo*_*one 5 java generics collections wildcard
首先,我将尝试解释此代码背后的想法.我有一堆类(处理器)可以处理某种类型的其他类(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) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,这似乎工作正常.没有编译错误.但现在我有一个类如下:
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
编译错误:
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>)
Run Code Online (Sandbox Code Playgroud)
我知道这可能有点难以阅读,但我试图尽可能地简化它.我对泛型也不是那么好,所以也许我用了一些通配符错了?任何人都可以帮我解决这个问题吗?
非常感谢提前!
如果我正确理解你的问题,我前段时间也问过类似的问题。简而言之,您无法按照您想要的方式使用这样的地图。好消息是您不需要它;)
问题是 Java 泛型是编译时的东西(您可能已经知道),它们仅存在于编译时,而不是当您实际填充List. 您无法找到一种用 Java 表达您的想法的方法,即使它看起来完全合法。
您可能会发现超级类型令牌在某些情况下对于提取参数很有用,并避免用户在合适的情况下提供显式参数(但请注意限制并考虑它们是否真的可以增加一些价值)。
简而言之,你最终会得到一个像这样的字段
private Map<Class<?>, List<?>> data;
Run Code Online (Sandbox Code Playgroud)
(或者您可以使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
219 次 |
| 最近记录: |