在Java中实现通用接口

我有一个Javagenerics问题我希望有人可以回答。 请考虑以下代码:

public interface Event{} public class AddressChanged implements Event{} public class AddressDiscarded implements Event{} public interface Handles{ public void handle(T event); } 

我想像这样实现这个Handles接口:

 public class AddressHandler implements Handles, Handles{ public void handle(AddressChanged e){} public void handle(AddressDiscarded e){} } 

但java不允许使用Generic两次实现Handles。 我能够用C#完成这个,但是如果不使用Reflection或instanceof和cast,就无法在java中找到解决方法。

java中有没有办法使用通用接口实现Handles接口? 或者也许是另一种编写Handles接口的方法,以便完成最终结果?

你不能用Java做到这一点。 您只能实现相同通用接口的一个具体实现。 我会这样做:

 public class AddressHandler implements Handles{ 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){} } 

追求@Amir Raminfar,您可以使用访客模式

 interface Event{ void accept(Visitor v); } interface Visitor { void visitAddressChanged(AddressChanged a); void visitAddressDiscarded(AddressDiscarded a); } class AddressChanged implements Event{ @Override public void accept(Visitor v) { v.visitAddressChanged(this); } } class AddressDiscarded implements Event{ @Override public void accept(Visitor v) { v.visitAddressDiscarded(this); } } class AddressHandler implements Visitor { void handle(Event e){ e.accept(this); } public void visitAddressChanged(AddressChanged e){} public void visitAddressDiscarded(AddressDiscarded e){} } 

不,因为Java中不同的“具体”generics类型编译为相同类型 。 您的对象将实现的实际接口是:

 public interface Handles { public void handle(Event event); } 

显然,你不能有两种不同的方法,具有相同的签名……

AFAIK你不能这样做,因为在用Java编译源代码时,这些都会归结为handle(Event) ,使得方法不明确。

与C#相反,通用信息在Java运行时期间不可用。 这就是为什么它如你所描述的那样有效。

您必须更改方法名称以使其唯一,例如handleAddressChangedhandleAddressDiscarded

这确实是Javagenerics的弱点之一。

不幸的是不是 通常的解决方案(胖,丑,快)是创建一个Handles接口(即HandlesAddressChangeHandlesAddressDiscarded )并为它们中的每一个提供不同的方法( handleAddressChange(...)handleAddressDiscarded() )。

这样,Java运行时可以区分它们。

或者您可以使用匿名类。

这是不允许的,因为Java在编译期间擦除了通用签名。 接口方法实际上会有签名

 public void handle(Object event); 

所以你有两个选择。 为不同的事件实现单独的处理程序:

 public class AddressChangedHandler implements Handles{ /* ... */ } public class AddressDiscardedHandler implements Handles{ /* ... */ } 

或为所有人实现一个处理程序,但检查传入事件的类型:

 public void handle(Event e){ if (e instanceof AddressChanged) { handleAdressChanged(e); } else if (e instanceof AddressDiscareded) { handleAdressDiscarded(e); } } 

由于java规范的限制,这样的实现将不起作用。 但是如果你不害怕使用AOP或某种IOC-Container,你可以使用注释。 比您的方面或容器可以管理消息传递基础结构并调用您注释的方法。

首先,您必须创建注释。

 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface EventConsumer {} @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Handles{} 

你可以这样注释你的class级:

 @EventConsumer public class AddressHandler{ @Handles public void handle(AddressChanged e){} @Handles public void handle(AddressDiscarded e){} } 
Interesting Posts