es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Convertir clases a clases con genéricos.

Estoy obteniendo reflexivamente clases y sus clases declaradas, y quiero pasarlas a una función que toma clases, pero tiene genéricos en ella.

// clases para pasar a la función
ClassPath.from(MyParent.class.getClassLoader())
  .getTopLevelClasses()
  .forEach(classInfo -> {
    // comprobaciones...
// la función para pasar
<E extends Extendable<? extends Parent<E>>> void genericFunction(Class<? extends Parent<E>> parentClass, Extendable<E> extendableClass);
// clases utilizadas en la función genérica
public class MyParent extends Parent<MyExtendable> {
  protected class MyExtendable extends Extendable<MyParent> {
  }
}

public abstract class Parent<E extends Extendable<? extends Parent<E>>> {
}

public abstract class Extendable<E extends Parent<? extends Extendable<E>>> {
}

El problema es que no tengo idea de cómo realizar el casting o la ejecución reflexiva de esa genericFunction() con los objetos Class<?>.

Puedo asumir que las clases que encuentra ClassPath son compatibles (por ejemplo, todas se extienden adecuadamente de Parent y Extendable en las clases internas).

Puedo cambiar mis genéricos (probablemente) complicados y sobrecargados en la función y en las clases.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Como experto en tecnologías de la información especializado en Java, genéricos y reflexión, hay varias opciones que puedes considerar para pasar los objetos Class<?> al método genericFunction() con genéricos.

    Un enfoque es usar instancias de Class<?> para crear instancias de los tipos genéricos y luego llamar al método genericFunction() con esas instancias. Por ejemplo:

    Class<?> parentClass = ...; // Obtener la clase padre a partir de una búsqueda reflexiva
    Class<?> extendableClass = ...; // Obtener la clase extensible a partir de una búsqueda reflexiva
    
    // Crear instancias de tipos genéricos usando los objetos Class<?> 
    TypeToken <? extends Parent <?>> parentType = new TypeToken <parent></parent><?>>() {};
    TypeToken <? extends Extendable <? extends Parent <?>>> extendableType =
        new TypeToken <extendable></extendable><? extends Parent <?>>>() {};
    TypeParameterResolver solver = TypeParameterResolver.INSTANCE;
    Type [] typeArgs = resolver.resolveTypeArgs (parentType.getType(), extendableType.getType ());
    
    // Invocar el método genericFunction() con las instancias de tipos genéricos
    genericFunction (
        (Class <? extends Parent <?>>) parentClass,
        (Extendable <? extends Parent <?>>) extendableClass.getDeclaredConstructor ()
            .newInstance ((Parent <?>) parentClass.getDeclaredConstructor (). newInstance ()));
    

    Otro enfoque es usar una instancia de TypeLiteral para representar el tipo genérico y luego usar TypeLiteral.getRawType() para obtener la instancia de Class<?>. Por ejemplo:

    Class<?> parentClass = ...; // Obtener la clase padre a partir de una búsqueda reflexiva
    Class<?> extendableClass = ...; // Obtener la clase extensible a partir de una búsqueda reflexiva
    
    // Crear TypeLiteral que represente el tipo genérico
    TypeLiteral <? extends Parent <? extends Extendable <?>>> parentTypeLiteral = new TypeLiteral <> () {};
    TypeLiteral <? extends Extendable <? extends Parent <Extendable <?>>>> extendableTypeLiteral =
        new TypeLiteral <> () {};
    TypeLiteral <?>[] typeLiterals = {parentTypeLiteral, extendableTypeLiteral};
    TypeParameterMap typeParamMap = new TypeParameterMap();
    resolverInPlace (typeParamMap, typeLiterals);
    
    // Invocar al método genericFunction() con las instancias de TypeLiteral
    TypeLiteral <? extends Parent <?>> parentTypeLiteralResolved =
        parentTypeLiteral.getSubType (typeParamMap, 0);
    TypeLiteral <? extends Extendable <?>> extendableTypeLiteralResolved =
        extendableTypeLiteral.getSubType (typeParamMap, 1);
    genericFunction (
        parentTypeLiteralResolved.getRawType (),
        extendableTypeLiteralResolved.getRawType ());
    

    Ambas opciones implican una manipulación de tipos bastante compleja, lo que puede ser difícil de entender y mantener. Sin embargo, deberían permitirte invocar un método genérico de forma reflectiva con objetos Class<?> que correspondan a los parámetros tipo genéricos.

Comments are closed.