java - Java:如何避免“方法不适用于参数”错误
问题描述
我意识到这种类型的问题已经被问过无数次了,但我还没有找到一个似乎可以解决和/或解释 1)我做错了什么和 2)我需要做些什么才能让它正确的答案。
我有一个应用程序,我正在尝试管理一组队列。队列管理器的用户将通过提供唯一 ID 来请求队列,如果队列已被管理,管理器将返回该队列,或者创建一个新队列(通过反射)并在尚未创建时返回它。
我已经对队列管理器进行了编码以使用 Java 泛型,并且遇到了一个我不理解的问题,也不知道如何解决这个问题。
这是队列管理器:
public class QueueManager<T extends MessageType, C extends BlockingQueue<T>> {
private Map<UUID, C> queueMap;
public void removeQueue(UUID id) {
queueMap.remove(id);
}
public C getQueue(Class<C> clazz, UUID id) {
if (!queueMap.containsKey(id)) {
queueMap.put(id, constructQueue(clazz));
}
return queueMap.get(id);
}
private C constructQueue(Class<C> clazz) {
C result = null;
try {
Constructor<C> constructor = clazz.getDeclaredConstructor();
result = constructor.newInstance();
} catch (NoSuchMethodException | SecurityException | InstantiationException
| IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// handle exception
}
return result;
}
}
使用队列管理器的代码:
public class QueueingListener<T extends MessageType> implements MessageListener<T> {
private QueueManager<T, BlockingQueue<T>> queueMgr = new QueueManager<>();
...
@Override
public void handleMessage(T message) {
...
queueMgr.getQueue(LinkedBlockingQueue.class,
message.getMessageHeader().getUUID());
...
}
该代码抱怨编译错误:
The method getQueue(Class<BlockingQueue<T>>, UUID) in the type QueueManager<T,BlockingQueue<T>> is not applicable for the arguments (Class<LinkedBlockingQueue>, UUID)
有人可以解释一下这里有什么问题以及我需要做什么吗?
我真的很想知道在哪里可以找到关于 Java 泛型的非常好的教程。我查看了许多资源,但它们似乎只涵盖了让某人继续前进的基础知识,而没有涵盖更高级的概念和更精细的细节。
解决方案
我将总结这段代码的重要部分,以说明我要提出的观点:
public class QueueManager<T extends MessageType, C extends BlockingQueue<T>> {
public C getQueue(Class<C> clazz, UUID id) {
if (!queueMap.containsKey(id)) {
queueMap.put(id, constructQueue(clazz));
}
return queueMap.get(id);
}
}
请注意,在最初创建此类的实例时,C 可以是任何扩展 BlockingQueue 的类。然而,一旦你创建了这个对象,C 就被设置为某种类型的特定类。您稍后调用以下代码:
private QueueManager<T, BlockingQueue<T>> queueMgr = new QueueManager<>();
上面的行将 C 定义为“BlockingQueue”。
queueMgr.getQueue(LinkedBlockingQueue.class, message.getMessageHeader().getUUID());
但是,在这一行中,您传入了一个完全不同的对象。LinkedBlockingQueue实现了 BlockingQueue,是的,但是两者的 Class 对象分别是完全不同的,并且它们不是由您的类描述指定的。您正在寻找的是在您的方法签名中扩展 C的一类东西。因此,解决此错误的方法是修改您的 getQueue() 方法,如下所示:
public <X extends C> C getQueue(Class<X> clazz, UUID id) {
if (!queueMap.containsKey(id)) {
queueMap.put(id, constructQueue(clazz));
}
return queueMap.get(id);
}
这里有一个微妙但重要的句法差异,我希望我已经解释清楚了。您还可以以类似的方式修改constructQueue()。:)
推荐阅读
- c# - 如果更改组合框值,则更改文本框值(System.FormatException:'输入字符串格式不正确。')
- statistics - 使用 Fama-MacBeth (1973) 方法测试 CAPM
- mule - 如何将mule4中的标头/查询参数设置为变量/有效负载?
- database - 如何使用 elasticsearch 创建子查询
- swift - 继续获取“命令 PhasescriptExecution 失败,退出代码为非零
- python - 展平时将张量与矩阵相乘
- swiftui - SwiftUI 和 CombineLatest 具有超过 4 个值
- sqlite - NoSQL 还是 SQLite 数据库更适合大量记录、GPS 跟踪 Flutter App?
- javascript - 自定义数组排序
- html - 按钮内的标签 - 单击按钮并激活标签