2014-10-11 54 views
2

好了,所以我想設計一個事件系統爲我自己,這是我到目前爲止的事件處理程序(事件是一些空類):正在檢索一個類的通用參數使用保證工作的反射方法(在我的情況)?

public interface EventHandler 
{ 
    public Class<? extends Event> type(); 

    public void handle(Event event); 
} 

的目標是,在事件處理程序只能處理一種類型的事件(在這一點上)。 不過,我想如果我能重新格式化這樣的:

public interface EventHandler <T extends Event> 
{ 
    public void handle(T event); 
} 

這將幫助我在兩個方面:

  • 的需要type()不見了。
  • 我不會在處理事件時施放。

基於這樣一個問題:Reflection for Class of generic parameter in Java?,我可以通過這種方法得到T

ParameterizedType t = (ParameterizedType) MyClass.class.getGenericSuperclass(); //OtherClass<String> 
Class<?> clazz = (Class<?>) t.getActualTypeArguments()[0]; // Class<String> 

我知道,像這樣的東西打交道時類型擦除是一個因素,但我不明白是什麼時候它適用於我的使用EventHandler<T>,或幾乎所有的說實話。例如,我會用EventHandler<T>的唯一途徑是,和裸陪我在這裏,因爲我只是做東西了:

public class TestEvent extends Event {} 

public class TestEventHandler implements EventHandler<TestEvent> 
{ 
    @Override 
    public void handle(TestEvent event) 
    { 
     System.out.println("Event Handled"); 
    } 
} 

(我的活動將是自己的包和處理將是另一個)

即將到來的事件總線將按類註冊該處理程序,並獲取它的通用事件類型以用作Event類和EventHandler映射中的鍵。

無論如何,任何澄清將不勝感激。如果我只能得到一半的時間或類似的泛型類型,那麼它不會工作,我可能不得不做一個沒有泛型類型的版本。如果您願意,可以隨意批評EventHandler的格式如何在您的答案中開始。

回答

1

這種反射技巧也用於類型的標記(看起來他們)。

這裏的type erasure發生

public class Generic<TypeParameter> { 
    public void method(TypeParameter parameter) { 
     // no way to know the type bound to TypeParameter due to Type Erasure 
    } 
} 

的一個例子,但它並不適用於你的情況。像

public class TestEventHandler extends EventHandler<TestEvent> 

的聲明非常明確。它使用TestEvent作爲泛型EventHandler類型的類型參數。更重要的是,方法聲明

@Override 
public void handle(TestEvent event) 
{ 
    System.out.println("Event Handled"); 
} 

也告訴我們該參數的類型爲TestEvent。這些信息在運行時不會丟失。它是Class信息的一部分(它在字節碼中)。

如果您繼續使用製作EventHandler類型(如TestEventHandler),則可以使用反射技巧獲取Event類型。請注意,您也可以使用匿名小類

new EventHandler<TestEvent>() {/*body*/}; 

實現相同的目的。

+0

感謝快速的解釋,但一個問題:你說,'公共類TestEventHandler擴展事件處理'是「明確的」。比方說,我做了一個不明確的例子,是否會像'public class TestEventHandler extends EventHandler''擴展EventHandler'? (不要問我爲什麼我甚至會這樣做) – octopod 2014-10-11 16:10:30

+0

@Octopod我只是用_explicit_這個詞來強調你知道你使用的是什麼類型。在你的評論中的TestEventHandler中,你正在使用一個類型變量。沒有辦法知道它的價值(類型綁定)_類別本身。 – 2014-10-11 16:18:20

0

您顯示的代碼依賴於MyClassEventHandler的直接實現類,而MyClass實現EventHandler的類型參數,其中具體類是類型參數。因此,它必須是這樣的:

class MyClass implements EventHandler<String> 

大多數的地方,這是使用的時間(例如用型令牌),用戶預計將創造直接實現EventHandler<String>這樣一個匿名類:new EventHandler<String>() { /* body of anonymous class, can be empty */ },這是相當於上面的名稱類型,除了匿名部分。

一些場景,其中的代碼將無法正常工作:

  • 如果MyClass是通用的,有型變量作爲類型參數,而不是一個具體的類實現EventHandler

    class MyClass<T> implements EventHandler<T> 
    
  • 如果MyClass不直接實現EventHandler,但會經歷一個或多個非通用類之間:

    class MyClass implements YourClass 
    class YourClass implements EventHandler<String> 
    

(在後一種情況下,將有可能對智能代碼來遍歷型結構,找到與EventHandler實施的說法,但它需要非常複雜的處理所有的情況下,例如YourClass本身可能是通用的,並且使用它的一個參數來實現EventHandler

相關問題