使用ByteBuddy定义具有通用类型的字段

geo*_*and 4 java byte-buddy

我刚开始与ByteBuddy一起玩,并且正在研究几个示例,以便掌握它。

我试图通过此练习完成的工作是用ByteBuddy替换一些使用ASM的代码。

到目前为止,当涉及到非泛型类型时,我已经取得了成功。例如,我可以轻松地定义一个像这样的字段

builder.defineField("names", List.class, Visibility.PRIVATE)
Run Code Online (Sandbox Code Playgroud)

如果我只想创建一个原始List类型的字段。

但是,在介绍泛型时,我很困惑。

显然,我定义字段的方式(使用Class)意味着通用类型会丢失。阅读文档(尤其是该Working with generic types部分)后,我无法真正弄清楚如果List字段具有已知的通用类型(例如,如果它是另一个POJO)如何构造List字段。假设我有以下POJO:

public class Dummy {
   private String name;

   //getters, setters
}
Run Code Online (Sandbox Code Playgroud)

并且我想创建一个的字段List<Dummy>,我将如何完成这样的任务?

谢谢!

k5_*_*k5_ 5

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();
Run Code Online (Sandbox Code Playgroud)

实际设置验证字段的一种方法,它包含通用参数就是该测试用例

    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]);
Run Code Online (Sandbox Code Playgroud)