用Java实现通用接口
我有一个Java泛型问题,我希望有人能回答。考虑下面的代码:用Java实现通用接口,java,generics,cqrs,Java,Generics,Cqrs,我有一个Java泛型问题,我希望有人能回答。考虑下面的代码: public interface Event{} public class AddressChanged implements Event{} public class AddressDiscarded implements Event{} public interface Handles<T extends Event>{ public void handle(T event); } 公共接口事件{} 公共类
public interface Event{}
public class AddressChanged implements Event{}
public class AddressDiscarded implements Event{}
public interface Handles<T extends Event>{
public void handle(T event);
}
公共接口事件{}
公共类AddressChanged实现事件{}
公共类AddressDiscarded实现事件{}
公共接口句柄{
公共无效句柄(T事件);
}
我想实现如下处理接口:
public class AddressHandler implements Handles<AddressChanged>, Handles<AddressDiscarded>{
public void handle(AddressChanged e){}
public void handle(AddressDiscarded e){}
}
公共类AddressHandler实现句柄,句柄{
公共无效句柄(地址已更改){}
公共无效句柄(地址){}
}
但是java不允许使用泛型实现两次句柄。我可以用C#完成这一点,但如果不使用反射或instanceof and casting,我就无法在java中找到解决方法
java中有没有一种方法可以使用两个通用接口来实现Handles接口?或者用另一种方法编写Handles接口,以实现最终结果?在Java中无法做到这一点。您只能实现同一通用接口的一个具体实现。我会这样做:
public class AddressHandler implements Handles<Event>{
public void handle(Event e){
if(e instanceof AddressDiscarded){
handleDiscarded(e);
} else if(e instanceof AddressChanged){
handleChanged(e);
}
}
public void handleDiscarded(AddressDiscarded e){}
public void handleChanged(AddressChanged e){}
}
公共类AddressHandler实现句柄{
公共无效句柄(事件e){
如果(地址的实例已丢弃){
已处理的文件(e);
}否则,如果(地址更改的实例){
改变手柄(e);
}
}
已处理的公共无效已存档(地址e){}
公共无效句柄已更改(地址已更改){}
}
AFAIK您不能这样做,因为在Java中编译源代码时,这两种方法都会归结为处理(事件)
,使得方法不明确
与C#相比,Java中的通用信息在运行时不可用。这就是为什么它能像你描述的那样工作
您必须更改方法名称以使其唯一,如handleAddressChanged
和handleAddressDiscarded
这确实是Java泛型的弱点之一。不,因为Java中不同的“具体”泛型类型编译为相同的类型。对象将实现的实际接口是:
public interface Handles {
public void handle(Event event);
}
而且,很明显,不能有两个具有相同签名的不同方法…在@Amir Raminfar之后,可以使用模式
不幸的是没有。通常的解决方案(胖、丑、快)是创建一个
句柄
接口(即HandlesAddressChange
,HandlesAddressDiscarded
),并为每个句柄提供不同的方法(HandledAddressChange(…)
,HandledAddressDiscarded()
)
这样,Java运行时就可以将它们区分开来
或者您可以使用匿名类。这是不允许的,因为Java在编译过程中会擦除通用签名。接口方法将实际具有签名
public void handle(Object event);
所以你有两个选择。为不同的事件实现不同的处理程序:
public class AddressChangedHandler implements Handles<AddressChanged>{ /* ... */ }
public class AddressDiscardedHandler implements Handles<AddressDiscarded>{ /* ... */ }
由于java规范的限制,这样的实现无法工作。 但是,如果您不怕使用AOP或某种IOC容器,您可以使用注释。您的方面或容器可以管理消息传递基础结构并调用您注释的方法 首先,您必须创建注释
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventConsumer {}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Handles{}
您可以这样注释您的类:
@EventConsumer
public class AddressHandler{
@Handles
public void handle(AddressChanged e){}
@Handles
public void handle(AddressDiscarded e){}
}
这是有争议的。。。这个“级联实例”是一个非常程序化的范例。当然可以,但我觉得不是很好的风格。但因此,使用不同的方法名称也可能不是完美的,这可能是一个品味问题。这就是我要做的。您不必:)@don:但同一个泛型接口的多个实例不是这样的。这就是我们要说的实际上,擦除将是
公共无效句柄(事件)代码>+1,但在模式中,事件“接受”访问者,访问者“访问”事件:)@robev,我忘了在那一行重命名它。谢谢修正了。这确实是一个编译时问题。您不需要知道对象的运行时属性(参数甚至可以是null
!)来区分方法。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventConsumer {}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Handles{}
@EventConsumer
public class AddressHandler{
@Handles
public void handle(AddressChanged e){}
@Handles
public void handle(AddressDiscarded e){}
}