Erasure类型的丑陋头脑,如何规避?

所以我有这个界面

public interface EventHandler { public void handleEvent(E event); } 

我想为它处理处理事件的类,如下所示:

 public class WorkingHandler implements EventHandler { public void handleEvent(MouseEvent event) { //handle event } } 

以上示例工作正常。 但是编译器不会让我多次实现EventHandler,因为类型擦除非常令人沮丧。

 public class NotWorkingHandler implements EventHandler, EventHandler { public void handleEvent(MouseEvent event) { //handle mouse event } public void handleEvent(KeyEvent event) { //handle key event } } 

几个问题……

  1. 为什么Java不允许Type Erasure? IIRC与早期版本的Java兼容是否正确,对吗?

编辑:我的意思是为什么Java有类型擦除(反过来说)

  1. 是否有任何类型的“mod”/“扩展”(缺少一个更好的词)或编程语言,让我绕过Type Erasure? 因为我没有使用旧版本的Java,所以我不关心我的代码是否与旧代码兼容。

  2. Java语言中是否有任何可以用来绕过Type Erasure的变通办法?

  3. 如果不是,在我的程序中编写事件处理的其他方法有哪些让编译器满意?

我不确定您对Java中类型擦除的理解是否正确。 如此处所述,generics类的类型在运行时会丢失。

回答你的问题:

  1. 我认为你是正确的,Java实现类型擦除,以实现与先前版本的语言兼容。
  2. 不,我不认为有“mod”。
  3. 没有没有变通方法(在编译时删除了类型),但您可以使用reflection。
  4. 见下文。

我认为一个更简单的解决方案是这样的:

 public class WorkingHandler implements EventHandler { public void handleEvent(EventObject event) { // handle event if (event instanceof MouseEvent) handleMouseEvent((MouseEvent) event); ... } ... private void handleMouseEvent(MouseEvent event) { // handle mice } } 

一种选择是使用Guava EventBus向订阅者发布事件。 它专门用于解决您目前面临的问题,以及其他问题。

有了它,你不需要实现任何接口……只需提供两个这样的@Subscribe方法:

 @Subscribe public void handleKeyEvent(KeyEvent event) { ... } @Subscribe public void handleMouseEvent(MouseEvent event) { ... } 

关于它的一些其他文档可以在Guava wiki上找到 。

类型Erasure很好,因为它意味着JVM不需要知道任何有关Generic类型的信息。 这也意味着使用Generic类型不会对性能产生影响。

此外,您关于需要保持二进制兼容性的想法是现场(如类型擦除教程中所示 )。 类型擦除允许在Java之前编写的代码允许通用类型与使用generics编写的Java代码无缝地互操作。

如何简单地制作两个处理程序并将它们连接起来?

 public class KeyHandler implements EventHandler { public void handleEvent(KeyEvent event) { //handle key event } } public class MouseHandler implements EventHandler { public void handleEvent(MouseEvent event) { //handle mouse event } } 
  1. 是的,实现了类型擦除,以便不必更改JVM的规范以运行新版本(实现generics的版本)。

  2. 正如其他人指出的那样,许多语言都不会影响类型擦除。 如果您正在寻找Java,可能,但我不确定 – 它不会因为1而无法在标准JVM上运行。

  3. 您可以执行通用事件处理程序:

 public class GenericHandler implements EventHandler { public void handleEvent(EventObject event) { if (event instanceof MouseEvent) { MouseEvent mouseEvent = (MouseEvent) event; //handle mouse event } else if (event instanceof KeyboardEvent) { KeyboardEvent keyboardEvent = (KeyboardEvent) event; //handle keyboard event } } } 

不是最优雅,但工作:)