Вопрос по generics, type-erasure, types, interface, java – Тип Erasure поднимает свою уродливую голову, как обойти?

5

Итак, у меня есть этот интерфейс

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

и я хочу получить классы для него, которые обрабатывают события, вот так:

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

Приведенный выше пример работает нормально. Но компилятор не позволил мне реализовать EventHandler несколько раз из-за очень расстраивает тип Erasure.

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

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

Несколько вопросов ...

Why does Java not allow Type Erasure? IIRC it is something to do with being compatible with earlier versions of Java, correct?

РЕДАКТИРОВАТЬ: я имею в виду, почему у Java есть Erasure типа (было наоборот)

Is there any sort of "mod"/"extension" (for lack of a better word) or programming languages that allow me to get around Type Erasure? As I am not using older versions of Java I don't care about my code being compatible with older code.

Are there any workarounds, within the Java language, that I can use to get around Type Erasure?

If no, what are some alternate ways to code event handling in my program that keeps the compiler happy?

Вы ищете C # David Heffernan
& quot; Почему Java не разрешает стирание типа? & quot; -- не имеет смысла. Java разрешает стирание типов - фактически она реализует стирание типов. emory
Это хорошая (полпопулярная) книга от Wadler, в которой рассматриваются ваши первые вопросы - в основном для обратной совместимости. andrew cooke
"Есть ли какой-нибудь" мод "/" расширение "? (из-за отсутствия лучшего слова) или языков программирования, которые позволяют мне обойти Type Erasure? & quot; - Да, во многих языках нет стирания типов. emory

Ваш Ответ

4   ответа
2

потому что это означает, что JVM не нужно ничего знать о типовых типах. Это также означает, что использование универсальных типов не влияет на производительность.

Кроме того, ваше представление о необходимости поддерживать двоичную совместимость является точным (как указано вТип Erasure учебник). Стирание типа позволяет коду, написанному до того, как Java разрешил универсальным типам, беспрепятственно взаимодействовать с кодом Java, написанным с использованием Generics.

Как насчет простого создания двух обработчиков и присоединения обоих?

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

гуайява EventBus отправлять события подписчикам. Он специально разработан для решения проблемы, с которой вы сталкиваетесь, помимо прочего.

При этом вам не нужно реализовывать какие-либо интерфейсы ... просто предоставьте два@Subscribe методы как это:

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

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

Некоторая дополнительная документация об этом доступна на Гуавевики.

1

type erasure is implemented so that the specifications of the JVM do not have to change in order to run the new version (one implementing generics).

As other pointed out many languages do not implment type erasure. If you are looking within Java, possibly, but I'm not sure -- not it won't work on standard JVMs precisely because of 1.

You can do a generic event handler:

.

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

Не самый элегантный, но работает :)

Вы можете избавиться от этого & quot; если instanceof ... & quot; Цепочка путем реализации шаблона проектирования Visitor и двойной отправки.
1

Воттип вашего универсального класса теряется во время выполнения.

В ответ на ваши вопросы:

I think you are right that Java implements type erasure to enable compatibility with previous versions of the langauge. No I don't think there is a "mod." No there are no workarounds (types are removed at compile time), but you can use reflection. See below.

Я думаю, что более простое решение было бы так:

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

Похожие вопросы