在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运行时期间不可用。 这就是为什么它如你所描述的那样有效。
您必须更改方法名称以使其唯一,例如handleAddressChanged
和handleAddressDiscarded
。
这确实是Javagenerics的弱点之一。
不幸的是不是 通常的解决方案(胖,丑,快)是创建一个Handles
接口(即HandlesAddressChange
, HandlesAddressDiscarded
)并为它们中的每一个提供不同的方法( 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){} }