So I have this interface
public interface EventHandler<E extends EventObject>
{
public void handleEvent(E event);
}
and I want to derive classes for it that handle events, like so:
public class WorkingHandler implements EventHandler<MouseEvent>
{
public void handleEvent(MouseEvent event)
{
//handle event
}
}
Above example works fine. But compiler won't let me implement EventHandler multiple times, due to the extremely frustrating 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
}
}
Several questions...
EDIT: I mean why does Java have Type Erasure (had it the other way around)
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?
One option is to use a Guava EventBus to post events to subscribers. It's specifically designed to address the issue you're currently facing, among other things.
With it, you don't need to implement any interfaces... just provide two @Subscribe
methods like this:
@Subscribe
public void handleKeyEvent(KeyEvent event) { ... }
@Subscribe
public void handleMouseEvent(MouseEvent event) { ... }
Some additional documentation on it is available on the Guava wiki.
Type Erasure is nice because it means that the JVM doesn't need to know anything about Generic types. This also means that there's no performance impact from using Generic types.
Also, your notion about the need to maintain binary compatibility is spot on (as indicated in the Type Erasure tutorial). Type erasure allows code written before Java allowed Generic types to interoperate seamlessly with Java code written using Generics.
How about simply making two handlers and attaching both?
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
}
}
I'm not sure that your understanding of Type Erasure in Java is correct. As explained here, the type of your generic class is lost at runtime.
In response to your questions:
I think a simpler solution would be to so something like this:
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
}
}
Yes, 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
}
}
}
Not the most elegant, but works :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With