避免返回通配符类型的方法

时间:2015-08-25 01:43:48

标签: java generics wildcard

这是我的应用程序设计,我试图避免从我的方法返回通配符类型,以便我可以调用返回对象上的方法。有什么建议?拥有一个静态实用程序方法来查找并返回正确的处理程序实现(如下所示)是不是一个好主意吗?

问题: 我有一堆请求(以及与之对应的响应)。必须处理这些请求,并且处理结果(响应)可以用于进一步处理。在给定时刻要处理哪个请求取决于几个标准(这是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)的类型相同。

1 个答案:

答案 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
}