Search code examples
javaoopgenerics

How resolve all actual types of an implementation class relative to a generic class or interface in java?


I'm trying to resolve all actual types of an implementation class relative to a generic class or interface.

I have written an ActualTypeArgumentsResolver for this, but it only works when the TypeName remains consistent. I want to ignore the TypeName and get all the actual types. How can I achieve this?

Any help would be greatly appreciated. Thank you!

@Test
public void testIndirectlyExtendedGenericSuperclassWithDiffTypeName() {

    abstract class AbstractClass3<AAA, BBB, CCC> { }

    abstract class AbstractClass2<AA, BB, CC> extends AbstractClass3<CC, Map, BB> { }

    abstract class AbstractClass1<A, B> extends AbstractClass2<Long, A, Boolean> { }

    class Impl extends AbstractClass1<String, Integer> {}

    Type[] arr = ActualTypeArgumentsResolver.resolve(Impl.class, AbstractClass3.class);

    Assert.assertTrue(arr.length == 3);
    Assert.assertEquals(arr[0], Boolean.class);
    Assert.assertEquals(arr[1], Map.class);
    Assert.assertEquals(arr[2], String.class);
}

Solution

  • Guava's TypeToken supports this. Use the getSupertype method on a TypeToken representing Impl to get the parameterised version of AbstractClass3 with all the actual type parameters.

    var token = TypeToken.of(Impl.class);
    var supertype = token.getSupertype(AbstractClass3.class).getType();
    var typeArgs = ((ParameterizedType)supertype).getActualTypeArguments();
    System.out.println(Arrays.toString(typeArgs));
    // output: 
    // [class java.lang.Boolean, interface java.util.Map, class java.lang.String]