5

所以我有这个界面

public interface EventHandler<E extends EventObject>
{   
    public void handleEvent(E event);
}

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

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

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

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

    public void handleEvent(KeyEvent event)
    {
        //handle key event
    }
}

几个问题...

  1. 为什么 Java 不允许类型擦除?IIRC 它与与早期版本的 Java 兼容有关,对吗?

编辑:我的意思是为什么 Java 有类型擦除(反之亦然)

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

  2. 在 Java 语言中是否有任何解决方法可以用来绕过类型擦除?

  3. 如果不是,有哪些替代方法可以在我的程序中编写事件处理代码以使编译器满意?

4

4 回答 4

5

一种选择是使用Guava EventBus将事件发布给订阅者。它专为解决您当前面临的问题而设计。

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

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

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

Guava wiki上提供了一些关于它的附加文档。

于 2012-04-15T22:32:06.247 回答
2

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

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

简单地制作两个处理程序并附加两者怎么样?

public class KeyHandler implements EventHandler<KeyEvent>
{
    public void handleEvent(KeyEvent event)
    {
        //handle key event
    }
}

public class MouseHandler implements EventHandler<MouseEvent>
{
    public void handleEvent(MouseEvent event)
    {
        //handle mouse event
    }
}
于 2012-04-15T22:28:51.283 回答
1

我不确定您对 Java 中类型擦除的理解是否正确。正如这里所解释的,您的泛型类的类型在运行时会丢失。

针对您的问题:

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

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

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

    ...

    private void handleMouseEvent(MouseEvent event)
    {
        // handle mice
    }
}
于 2012-04-15T22:37:16.140 回答
1
  1. 是的,类型擦除已实现,因此 JVM 的规范不必更改即可运行新版本(实现泛型)。

  2. 正如其他人指出的那样,许多语言没有实现类型擦除。如果您可能正在查看 Java,但我不确定 - 不是因为 1.

  3. 你可以做一个通用的事件处理程序:

.

public class GenericHandler implements EventHandler<EventObject> 
{ 
  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 
    }
  } 
} 

不是最优雅的,但很有效:)

于 2012-04-15T22:34:49.947 回答