mardi 5 janvier 2021

Is it possible to obtain the generic type of an interface?

Given the interface:

interface GenericInterface<T> {
  Class<T> getGenericType();
}

and the following implementation "skeletons":

class GenericInterfaceImpl<T> implements GenericInterface<T> { /* impl */ }

class TypedInterfaceImpl implements GenericInterface<String> { /* impl */ }

define an implementation for getGenericType in a manner that it would pass the following assertions:

assertEquals(new GenericInterfaceImpl<String>().getGenericType(), String.class, "Type should resolve to String.class");

assertEquals(new TypedInterfaceImpl().getGenericType(), String.class, "Type should resolve to String.class");

I'm perfectly aware of a good implementation that solves this problem on the TypedInterfaceImpl "scenario". The following code passes the assertion for the second case:

@Override
@SuppressWarnings("unchecked")
Class<T> getGenericType() {
    Type t = this.getClass().getGenericInterfaces()[0];
    ParameterizedType pt = (ParameterizedType) t;

    return (Class<T>) pt.getActualTypeArguments()[0];
}

But I can't find a way to get the same result if I'm working with the GenericInterfaceImpl version of this problem. When using the above implementation with GenericInterfaceImpl, the "type argument" resolves to a sun.reflect.generics.reflectiveObjects.TypeVariableImpl instead of java.lang.String like it does when handling TypedInterfaceImpl.

The Javadocs for getGenericInterfaces explicitly states that it will not resolve type parameters if it's not defined in the source code (for reference: https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getGenericInterfaces-- I'm using Java 11 in my particular case but it's the same nonetheless), so by definition, I understand that this particular method can't solve this problem.

Is there a way to solve this problem at all or is this a "core limitation" of the Java language?





Aucun commentaire:

Enregistrer un commentaire