2012-04-15 40 views
5

所以我有這個接口類型擦除醜陋的頭部,如何規避?

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

,我想獲得處理事件的,像這樣的IT類:

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的不允許類型擦除? IIRC它與Java的早期版本兼容是正確的嗎?

編輯:我的意思是爲什麼Java的有類型擦除(有它周圍的其他方法)

  1. 是否有任何形式的「MOD」 /「擴展」(由於缺乏一個更好的詞)還是允許我解決Type Erasure的編程語言?由於我不使用舊版Java,因此我不關心我的代碼與舊代碼兼容。

  2. 在Java語言中是否有任何可用於解決Type Erasure的變通方法?

  3. 如果否,那麼在我的程序中編寫事件處理的一些替代方法是什麼?

+4

- 沒有意義。 Java確實允許類型擦除 - 實際上它實現了類型擦除。 – emory 2012-04-15 22:21:20

+0

「是否有任何一種」mod「/」extension「(缺少更好的單詞)或編程語言讓我可以繞過Type Erasure?」 - 是的,許多語言沒有類型擦除。 – emory 2012-04-15 22:22:13

+1

您正在尋找C# – 2012-04-15 22:23:28

回答

1

我不知道你在Java的類型擦除的理解是正確的。如解釋here,您的泛型類的類型在運行時會丟失。

在回答你的問題:

  1. 我認爲你是對的Java實現類型擦除,以使與的langauge的以前版本的兼容性。
  2. 不,我不認爲有一個「國防部」。
  3. 不,沒有解決方法(在編譯時刪除類型),但可以使用反射。
  4. 見下文。

我認爲,一個簡單的解決辦法是使這樣的事情:「爲什麼Java的不允許類型擦除」

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

類型擦除是很好的,因爲這意味着JVM不需要知道關於泛型類型的任何信息。這也意味着使用泛型類型不會影響性能。

此外,您需要保持二進制兼容性的概念是現貨(如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 
    } 
} 
5

一種選擇是使用GuavaEventBus發佈事件給用戶。它專門設計用於解決您當前面臨的問題等等。

有了它,你不需要實現任何接口...只是提供類似下面的兩種@Subscribe方法:

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

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

一些額外的文件上它是可用的番石榴wiki

1
  1. 是的,類型擦除的實現使得爲了運行新版本(一個實現泛型),JVM的規格不必改變。

  2. 正如其他人指出的許多語言不implment類型擦除。如果您正在尋找在Java中,可能是,但我不知道 - 沒有它不會在標準的JVM工作正是因爲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 
    } 
    } 
} 

不是最優雅,但工程:)

+2

通過實現Visitor設計模式和雙重調度,您可以擺脫此「if instanceof ...」鏈。 – 2012-04-15 22:45:05