2017-08-24 161 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]);