这是我的应用程序设计,我试图避免从我的方法返回通配符类型,以便我可以调用返回对象上的方法。有什么建议?拥有一个静态实用程序方法来查找并返回正确的处理程序实现(如下所示)是不是一个好主意吗?
问题:
我有一堆请求(以及与之对应的响应)。必须处理这些请求,并且处理结果(响应)可以用于进一步处理。在给定时刻要处理哪个请求取决于几个标准(这是enum
)。
我的方法: 我的解决方案是构建多个处理程序,每个处理程序对应一个请求 - 响应类型组合,并让它们都实现一个通用接口和一个处理请求的方法。
这是怎么回事:
实现Handler
接口的一系列处理程序类:
interface Handler<Q extends Request, R extends Response> {
R handleRequest(Q);
}
和一个静态实用程序方法伴侣类,用于查找与给定条件匹配的正确处理程序:
class Handlers {
Handler<? extends Request, ? extends Response> handlerForCriteria(Criteria criteria) {
switch (criteria):
...
// since there are several handler implementations, I couldn't avoid the wildcard
// types for the request and response
}
}
这是我需要使用它的地方:
Handler<? extends Request, ? extends Response> matchingHandler =
Handlers.handlerForCriteria(criteria);
MyResponse response = matchingHandler.handleRequest(myRequest);
我希望能够像上面那样调用handleRequest
,但显然我不被允许,因为matchingHandler
包含通配符类型(它无法确定是否未知请求的通配符类型与`myRequest)的类型相同。
答案 0 :(得分:1)
如有必要,请使用带有强制转换的类型化方法:
class Handlers {
<R extends Request, T extends Response> Handler<R, T> handlerForCriteria(Criteria criteria) {
Handler<?, ?> handler = someStrategryThatIsUntyped();
return (Handler<R, T>)handler; // just cast
}
}
那么,为什么/何时演员“安全”?
有时案件既需要又安全。例如,请考虑以下代码:
private Map<Class<?>, Handler<?>> handlers = new HashMap<>();
然后以一种方式填充它,以保证类的类型等于处理程序的类型(在map的声明中无法完成):
public <T> void register(Class<T> clazz, Handler<T> handler) {
handlers.put(clazz, handler);
}
但无法根据地图的定义安全地编译找到处理程序的方法:
public <T> Handler<T> findHandler(Class<T> clazz) {
Handler<?> handler = handlers.get(clazz);
// Although the compiler can't assert it, the handler is of type T
// The cast is safe, because we programmatically constrain map's entries
return (Handler<T>)handler; // safe
}