类型Erasure看起来丑陋,如何规避?

时间:2012-04-15 22:14:32

标签: java generics types interface type-erasure

所以我有这个界面

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,因为 非常令人沮丧的Type Erasure。

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不允许Type Erasure? IIRC是否与早期版本的Java兼容,这是正确的吗?
  2. 编辑:我的意思是为什么Java有类型擦除(反过来说)

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

    2. 我是否可以使用Java语言中的任何变通方法来解决Type Erasure?

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

4 个答案:

答案 0 :(得分:5)

一种选择是使用Guava EventBus向订阅者发布活动。它专门用于解决您目前面临的问题,等等。

有了它,您不需要实现任何接口......只需提供两个@Subscribe方法,如下所示:

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

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

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

答案 1 :(得分:2)

类型擦除很好,因为这意味着JVM不需要了解有关通用类型的任何信息。这也意味着使用Generic类型不会对性能产生影响。

此外,您关于需要保持二进制兼容性的想法是现场开启(如Type Erasure tutorial所示)。类型擦除允许在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
    }
}

答案 2 :(得分:1)

  1. 是,已实施类型擦除,因此无需更改JVM的规范即可运行新版本(实现泛型的版本)。

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

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

  4. 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 
        }
      } 
    } 
    

    不是最优雅,但有效:)

答案 3 :(得分:1)

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

回答你的问题:

  1. 我认为你是正确的,Java实现了类型擦除,以实现与先前版本的langauge的兼容性。
  2. 不,我不认为有一个&#34; mod。&#34;
  3. 没有没有变通方法(在编译时删除了类型),但您可以使用反射。
  4. 见下文。
  5. 我认为更简单的解决方案就是这样:

    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
        }
    }