Generics getActualTypeArguments

Ich habe mal eine Frage zu Generics

wenn ich

public class Entity {
         // ....
}
public class GenericDAO<T> {
          public GenericDAO() {
              Type              t  = getClass().getGenericSuperclass();
              ParameterizedType pt = (ParameterizedType) t;
              
              type = (Class) pt.getActualTypeArguments()[0];              
              this.em = EntityManagerUtil.getEntityManager();
       }
}
public class Serivce {
         private GenericDAO<Entity> dao = new GenericDAO<Entity>()
}

wird mir ausgegeben

java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

ausgeben welches von

ParameterizedType pt = (ParameterizedType) t;

des Constructors der GenericDAO herrührt. Wie müsste es denn korrekt lauten?

Ich vermute mal, das liegt an Type Erasure: Zur Compilezeit geht die generischen Typinformationen verloren. Ich vermute mal, folgendes würde funktionieren:

public class EntityDAO extends GenericDAO<Entity>{}

public class Serivce {
         private EntityDAO  dao = new EntityDAO ();
}

Durch die Signatur von EntityDAO wird T = Entity sozusagen konserviert, und ist dann auch mit Reflection zu ermitteln.

Etwas mehr dazu: Advanced Java generics: retreiving generic type arguments

Tatsächlich würde schon ein

private GenericDAO<Entity> dao = new GenericDAO<Entity>() { /* This is an anonymous class */ };

reichen. Das nutzen die bei den TypeTokens in Guava https://code.google.com/p/guava-libraries/wiki/ReflectionExplained bis zum Anschlag aus.

auf Annotations, Reflection über Class-Object hinaus und insbesondere hinsichtlich Generics für Fachlogik des Programms besser verzichten,
das ist nicht das reine (schottische :wink: ) Java

wenn du das Class-Object brauchst, dann übergib es im Konstruktor,

bisschen Code
[spoiler]```
public class Test2 {
public static void main(String[] args) {
GenericDAO pdao = createDAO(Person.class);
}

static <T extends BaseEntity>GenericDAO<T> createDAO(Class<T> typ)  {
    return new GenericDAO<>(typ);
}

}

class Person extends BaseEntity {}

class BaseEntity{}

class GenericDAO {
Class type;

public GenericDAO(Class<T> typ)  {
    this.type = typ;
}

}



auch eine Enum für alle möglichen Typen nicht zuviel der Mühe, falls es helfen kann

was willst du mit der type-Variable dann anfangen?

Das klappt nur direkt in dem Konstruktor des GenericDAOs nicht. Denn GenericDAO hat keinen generic Supertype. Damit es klappt, müssen zwei Voraussetzungen erfüllt sein:

  1. Lager die Logik in eine Methode aus
  2. In Subklassen von GenericDAO klappt es. Die haben dann einen generic Supertype.

Du solltest GenericDAO abstract machen, um die Erzeugung von Instanzen davon wirksam zu verhindern. Falls Du das nicht möchtest, bleibt nur der Weg ohne Reflection, bei Dem du das Class-Objekt übergibst.