geoand
geoand

Reputation: 64011

Define field with generic type using ByteBuddy

I just started playing with ByteBuddy and I am working on a couple examples in order to get the hang of it.

What I am trying to accomplish with this exercise is to replace some code that uses ASM, with ByteBuddy.

So far I have been successful when it comes to non-generic types. For example I can easily define a field for example like this

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

if all I want to do is create a field of raw List type.

When it comes to introducing generics however, I am stuck.

Obviously the way I have defined the field (using a Class) means that the generic types are lost. Reading the documentation (especially the Working with generic types part), I can't really figure out how I would construct a List field if it has a known generic type, like for example if it's another POJO. Let's say I have the following POJO:

public class Dummy {
   private String name;

   //getters, setters
}

and I want to create a field of List<Dummy>, how would I accomplish such a task?

Thanks!

Upvotes: 5

Views: 1810

Answers (1)

k5_
k5_

Reputation: 5558

Instead of providing a Class<List> to the defineField method, you can provide a Type. ByteBuddy has a helper class to create generic Types so you don't need to create an implementation yourself. I put it on a separate line to make it more visible.

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

One way of validating the field is actually set and contains the generic parameters would be this testcase

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

Upvotes: 6

Related Questions