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 } }
几个问题……
- 为什么Java不允许Type Erasure? IIRC与早期版本的Java兼容是否正确,对吗?
编辑:我的意思是为什么Java有类型擦除(反过来说)
-
是否有任何类型的“mod”/“扩展”(缺少一个更好的词)或编程语言,让我绕过Type Erasure? 因为我没有使用旧版本的Java,所以我不关心我的代码是否与旧代码兼容。
-
Java语言中是否有任何可以用来绕过Type Erasure的变通办法?
-
如果不是,在我的程序中编写事件处理的其他方法有哪些让编译器满意?
我不确定您对Java中类型擦除的理解是否正确。 如此处所述,generics类的类型在运行时会丢失。
回答你的问题:
- 我认为你是正确的,Java实现类型擦除,以实现与先前版本的语言兼容。
- 不,我不认为有“mod”。
- 没有没有变通方法(在编译时删除了类型),但您可以使用reflection。
- 见下文。
我认为一个更简单的解决方案是这样的:
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 } }
-
是的,实现了类型擦除,以便不必更改JVM的规范以运行新版本(实现generics的版本)。
-
正如其他人指出的那样,许多语言都不会影响类型擦除。 如果您正在寻找Java,可能,但我不确定 – 它不会因为1而无法在标准JVM上运行。
-
您可以执行通用事件处理程序:
。
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 } } }
不是最优雅,但工作:)