在implements中使用泛型“super”/扩展类声明的一部分

时间:2014-09-08 08:09:50

标签: java generics

我有以下声明:

public interface Event<K> {}
public interface DataEvent<K, D> extends Event<K> {}
public interface OriginatedEvent<K, O> extends Event<K> {}

public class ErrorEvent<O, E extends Throwable> implements OriginatedEvent<Class<? extends ErrorEvent<O, E>>, O>, DataEvent<Class<? extends ErrorEvent<O, E>>, E> {}

public interface EventHandler<K, E extends Event<K>> {

public abstract class AbstractEventErrorHandler<O, E extends ErrorEvent<O, ? extends Throwable>> implements EventHandler<Class<E>, E> {}

我明白了:Bound mismatch: The type E is not a valid substitute for the bounded parameter <E extends Event<K>> of the type EventHandler<K,E>

在最后一部分implements EventHandler<Class<E>, E> {}

如果我改变:public abstract class AbstractEventErrorHandler<O, E extends ErrorEvent<O, ? extends Throwable>> implements EventHandler<Class<E>, E> {} 并且:public interface EventHandler<K, E extends Event<? super K>>

至:public abstract class AbstractEventErrorHandler<O, E extends ErrorEvent<O, ? super Throwable>> implements EventHandler<Class<E>, E> {} 并且:public interface EventHandler<K, E extends Event<K>>

它不再有错误(但我稍后会遇到其他问题,见下文)。我试图找到关于这个的文档来更好地设计我的泛型并理解它为什么这样做但是我找不到任何有用的东西,人们要么谈论在方法参数中使用extends / super,要么只在类/接口签名中扩展,任何在类/接口签名中提到super只是说它在声明的第一部分是不允许的。在我的情况下,我不在签名的声明部分使用它,而是在继承部分使用它。

我看过PECS? (Producer Extends,Consumer Super)但这似乎对方法声明有效;在类/接口中,它可以在代码中稍后使用。

有人可以向我解释或指出一个很好的解释吗?

如果我像上面提到的那样改变它并尝试使用我的AbstractEventErrorHandler类:

public abstract class AbstractEventBusErrorHandler extends AbstractEventErrorHandler<LocalEventBus, ErrorEvent<LocalEventBus, EventBusException>> {}

它给了我: Bound mismatch: The type ErrorEvent<LocalEventBus, EventBusException> is not a valid substitute for the bounded parameter <E extends ErrorEvent<O,? super Throwable>> of the type AbstractEventErrorHandler<O,E>?

谢谢

1 个答案:

答案 0 :(得分:0)

我认为你的通用类型错了。

而不是

public abstract class AbstractEventErrorHandler< O, E extends ErrorEvent<O, ? extends Throwable>> implements EventHandler<Class<E>, E> {}

您可能想要使用

public abstract class AbstractEventErrorHandler<O, E extends ErrorEvent<O, ? extends Throwable>> implements EventHandler<Class<O>, E> {}

问题在于,EventHandler期望第一个类型Class<E>成为ErrorEvent的第一个类型Class<O>,因为ErrorEvent实现了与Class<K>

顺便说一下,你应该尝试坚持每种类型一个名字,即从K切换到O可能会造成一些混乱。

<强>更新

我重新阅读了您的问题,当我将代码复制到IDE进行测试时,我认为我错过了一个定义。所以废弃上面的内容。

事实上,它似乎比上面容易:

您宣布ErrorEvent同时使用包含通配符的第一个类型实现OriginatedEventDataEventClass<? extends ErrorEvent<O, E>

这些通配符总是被解析为不同的类型,因此编译器在尝试解析最后一行的implements EventHandler<Class<E>, E>时会感到困惑(Class<E>只能匹配其中一个通配符,因此另一个没有&# 39; t匹配)。

要解决此问题,您需要为通配符引入一种类型,例如:

public class ErrorEvent<O, E extends Throwable, K extends ErrorEvent<O, E, ?>>  
   implements OriginatedEvent<Class<K>, O>, DataEvent<Class<K>, E> {}

然后在您的错误处理程序中,您声明KE

public abstract class AbstractEventErrorHandler<O, E extends ErrorEvent<O, ? extends Throwable, E>> implements EventHandler<Class<E>, E> {}