【发布时间】:2020-08-07 11:49:40
【问题描述】:
在 Java 中有什么方法可以使用一个泛型类作为另一个泛型类的类型参数?
例如,我有Message和MessageBus这样的:
public interface Message<V> {};
public interface MessageBus {
<V> V execute(Message<V> message);
}
现在效果很好。
然后,我得到 Command 和 CommandBus 像这样:
public interface Command<V> {};
public interface CommandBus {
<V> V execute(Command<V> command);
}
它也很好用。
但是,CommandBus 的实现与MessageBus 几乎相同。
我想将MessageBus 定义为这样的泛型类:
public interface Message<V> {};
public interface MessageBus<T extends Message> {};
public interface Command<V> extends Message<V> {};
public interface CommandBus extends MessageBus<Command> {};
看起来还不错,但是当我想定义方法execute时出现问题:
public interface MessageBus<T extends Message> {
<V> V execute(T<V> message); // compiles error, T<V> is invalid
<V> V execute(T message); // T means Message<Object>, not Message<V>
<V> V execute(Message<V> message); // CommandBus cannot override Message<V> to Command<V> in subclass
}
请注意,V 在每次调用时都是不同的类型,所以我不能像这样定义MessageBus:
public interface MessageBus<V, T extends Message<V>> {
/**
* In this way, each bus can have only one fixed return type.
* But different return type is expected on different message,
* just like the first interface above.
*/
V execute(T message);
}
我想这样使用它们:
public class Command1 implements Command<Integer> {};
public class Command2 implements Command<String> {};
public class Command3 implements Command<String> {};
public class Message1 implements Message<String> {};
CommandBus commandBus;
Integer v1 = commandBus.execute(new Command1()); // fine
String v2 = commandBus.execute(new Command2()); // fine
String v3 = commandBus.execute(new Command3()); // fine
String v4 = commandBus.execute(new Command1()); // should compile error, return type mismatch
String v5 = commandBus.execute(new Message1()); // should compile error, only support Command
我会有各种MessageBus,比如CommandBus extends MessageBus<Command>、QueryBus extends MessageBus<Query>、EventBus extends MessageBus<Event>等等。
我将如何实现这种行为?
谢谢。
【问题讨论】:
-
Message<T>中的T突然不见了?这就是前面代码中返回的内容。 -
@daniu 这就是问题所在:返回类型
V应该是方法execute上的泛型类型,而不是类MessageBus上的泛型类型。当Message转到MessageBus的类型参数时,V不能去那里。 (我编辑了问题并将Message<T>重命名为Message<V>,因为它与MessageBus<T extends Message>中的T不同)