假设我有一个简单的类:
假设我有BigObjects和SmallObjects(它们都扩展了MyObject),我想为它们创建单独的处理程序。因此,我使用特定泛型创建了两个MyObjectHandler接口。
现在让我们想象一下,我们已经创建了
问题:是否可能为这种情况创建完美的AbstractHandlerChain?
这个可行,但在这种情况下我应该将BigHandlerChain定义为
这里有一个解决方案,我期望用Java实现,但它不起作用!我无法像这样声明类:
public class MyObject {
}
处理MyObject子类的处理程序接口
public interface MyObjectHandler<V extends MyObject>{
List<V> handle(List<V> objects);
}
假设我有BigObjects和SmallObjects(它们都扩展了MyObject),我想为它们创建单独的处理程序。因此,我使用特定泛型创建了两个MyObjectHandler接口。
class BigObject extends MyObject {}
class SmallObject extends MyObject {}
// Handlers interfaces
interface BigObjectHandler extends MyObjectHandler<BigObject>{}
interface SmallObjectHandler extends MyObjectHandler<SmallObject>{}
// Concrete handlers
class BigHandler1 implements BigObjectHandler {....}
class BigHandler2 implements BigObjectHandler {....}
class SmallHandler1 implements SmallObjectHandler {....}
class SmallHandler2 implements SmallObjectHandler {....}
现在让我们想象一下,我们已经创建了
AbstractHandlerChain<...>
抽象类。那么,我们可以创建 BigHandlerChain 类并注入我们的 BigHandlers(SmallHandlerChain 同理)。class BigHandlerChain extends AbstractHandlerChain<BigObjectHandler> {
// Inject only childs of BigObjectHandler. E.g. via spring @Autowired
public BigHandlerChain(List<BigObjectHandler> handlers) {
this.handlers = handlers;
}
}
问题:是否可能为这种情况创建完美的AbstractHandlerChain?
可能的解决方案1
public abstract class HandlerChain<T extends MyObjectHandler> {
private List<T> handlers;
public HandlerChain(List<T> handlers) {
this.handlers = handlers;
}
public <V extends MyObject> List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
这个方案是可行的,但在 handler.handle(objects)
中,我得到了一个关于原始类型 'MyObjectHandler' 的 unchecked call to 'handle(List<V>)' 的警告,因此我需要添加 @SuppressWarnings("unchecked")
,但这并不是很好的解决方法。
可能的解决方案2
public abstract class HandlerChain<T extends MyObjectHandler<? extends MyObject>> {
...
public <V extends MyObject> List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
不起作用。在handler.handle(objects)
中,我得到了错误信息:handle (java.util.List<capture<? extends MyObject>>) cannot be applied to (java.util.List<V>)
。为什么我不能在这种情况下将objects传递给handlers?通配符extends MyObject和V extends MyObject。难道这不足够吗?
可能的解决方案3
public abstract class HandlerChain<T extends MyObjectHandler<V>, V extends MyObject> {
...
public List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
这个可行,但在这种情况下我应该将BigHandlerChain定义为
class BigHandlerChain extends AbstractHandlerChain<BigObjectHandler, BigObject>
。但是BigObjectHandler
已经包含了它可以处理的类的信息,因此这是信息重复。public abstract class HandlerChain<T extends MyObjectHandler<V extends MyObject>> {
...
public List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
这里有一个解决方案,我期望用Java实现,但它不起作用!我无法像这样声明类:
...class HandlerChain<T extends MyObjectHandler<V extends MyObject>
。为什么我可以在MyObjectHandler之后使用通配符,但不能使用这种构造方法?
<T extends MyObjectHandler<V extends MyObject>>
中的 V 声明 V,但实际上 Java 编译器希望它已经被声明了。很遗憾,你并不是唯一一个希望如此的人。但事实就是这样。你的研究是正确的,你没有错过任何东西。 - Chris K