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

Define field with generic type using ByteBuddy

我刚开始玩 ByteBuddy,我正在研究几个示例以掌握它的窍门。

我想通过这个练习完成的是用 ByteBuddy 替换一些使用 ASM 的代码。

到目前为止,我在非泛型方面取得了成功。例如,我可以很容易地定义一个字段,例如这样

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

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

然而,当谈到引入泛型时,我被卡住了。

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

public class Dummy {
   private String name;

   //getters, setters
}

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

谢谢!

您可以提供 Type,而不是向 defineField 方法提供 Class<List>。 ByteBuddy 有一个助手 class 来创建通用类型,因此您不需要自己创建一个实现。我把它放在单独的一行以使其更明显。

    // 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]);