2017-08-24 158 views
2

我剛剛開始使用ByteBuddy進行遊戲,我正在處理幾個示例以獲取它的掛起。使用ByteBuddy定義具有泛型類型的字段

我試圖完成的這個練習是用ByteBuddy替換一些使用ASM的代碼。

到目前爲止,我非常成功地談到非泛型類型。例如,我可以很容易地定義一個字段,例如像這樣

builder.defineField("names", List.class, Visibility.PRIVATE) 

如果所有我想要做的就是創建原始List類型的字段。

但是,在介紹泛型時,我被卡住了。

很明顯,我定義該字段的方式(使用Class)意味着泛型會丟失。讀取documentation(尤其是Working with generic types部分),我無法弄清楚如何構建List字段(如果它具有已知的泛型類型),例如,如果它是另一個POJO。比方說,我有以下POJO:

public class Dummy { 
    private String name; 

    //getters, setters 
} 

,我想創建的List<Dummy>一個領域,我將如何完成這樣的任務呢?

謝謝!

+0

只是爲了記錄:你知道類型擦除,而事實上,生成的類沒有按不知道一個領域是一個專門的虛擬列表? – GhostCat

+0

@GhostCat當然可以!然而,有一些'神奇'的案例,我**可以**知道被擦除的類型(例如見傑克遜) – geoand

+2

當然,生成的類知道它的通用字段簽名。擦除意味着泛型類的實例不知道它的泛型類型。但它知道其成員的通用類型。 –

回答

2

而不是提供Class<List>到defineField方法,您可以提供一個Type。 ByteBuddy有一個幫助類來創建泛型類型,所以你不需要自己創建一個實現。我把它放在一個單獨的行中,使其更加醒目。驗證領域的

// Create List<Dummy> as Type 
    Generic generic = TypeDescription.Generic.Builder 
      .parameterizedType(List.class, Dummy.class).build(); 

    Class<? extends Example> loaded = new ByteBuddy().subclass(Example.class) 
      .defineField("names", generic, Visibility.PRIVATE).make() 
      .load(ByteBuddyEnhancer.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION).getLoaded(); 

一種方式是實際設置,幷包含通用參數應該是這樣的測試用例

Field field = loaded.getDeclaredField("names"); 
    Type fieldType = field.getGenericType(); 
    Assert.assertTrue(fieldType instanceof ParameterizedType); 
    ParameterizedType genericFieldType = (ParameterizedType)fieldType; 
    Assert.assertEquals(Dummy.class, genericFieldType.getActualTypeArguments()[0]); 
    System.out.println(genericFieldType.getRawType()); 
    System.out.println(genericFieldType.getActualTypeArguments()[0]);