2009-10-02 10 views
-2

Est-il possible de quelque chose comme:Java génériques (effacement de type)

Widget w = Gadet<Widget>().getInstance(); 

(Edit: invocation getInstance retourne une instance nouvellement créée du paramètre de type générique spécifié) Je ne sais au sujet de l'effacement de type java (atleast dans une certaine mesure). Mais je suis un peu confus quand je suis tombé sur

this.instanceClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 

sur hibernate.org

+0

Pourquoi cette "question supprimée"? Comment peut-il aider les autres? –

Répondre

2

Vous voulez passer dans toutes les classes, et d'obtenir une instance de ce type - statiquement, à savoir sans réflexion? Non, ce n'est pas possible - en raison de l'effacement de type, à droite.

La seule façon de passer dans une classe est de passer comme paramètre:

Object getInstance(Class clz){ ... }; 

Même si vous définissez comme

Object getInstance(Class<T> clz){ ... }; 

T est perdue lors de l'exécution. Tout ce que vous avez est classe. Je suppose que les concepteurs de langage pourraient le rendre plus doux en permettant des choses comme:

new T() 

qui, sous le capot ferait clz.newInstance(), mais ils ne l'ont pas.

+0

ah, désolé pour la courte explication dans la question. je l'ai édité – Schildmeijer

+0

'new T()' n'est pas autorisé car il suppose qu'un constructeur sans-argument existe, ce qui n'est pas vrai pour toutes les variantes de 'T', et non exécutable en utilisant le mécanisme de type Java. –

+0

Si le programme par défaut n'existe pas, lancez une exception en cours d'exécution.Ce serait juste une syntaxe suger pour Class.newInstance(), après tout. –

1

Vous pouvez faire quelque chose comme ce qui suit:

public static <T> T getInstance(Class<T> klass) { 
    try { 
     return klass.newInstance(); 
    } catch (Exception ex) { 
     //Do some real error handling here probably 
     return null; 
    } 
} 
2

Hm ... pour répondre pleinement à votre question, un peu de fond est nécessaire:

Erasure signifie que les paramètres de type réel ne sont pas inclus dans le bytecode , et donc le type dynamique d'un paramètre de type est inconnu à l'exécution, ce qui rend généralement impossible de l'instancier. (Par conséquent, new T() pour un paramètre de type T ne compile pas.)

Cependant, les paramètres de type réels spécifiés dans les déclarations de champs, de méthodes ou de classes sont enregistrés dans le fichier de classe et disponibles pour la réflexion. Dans certaines circonstances, cette dernière information est suffisante pour déterminer la valeur du paramètre de type.

Par exemple, l'extrait du site de mise en veille prolongée, si elle est déclarée en classe C<T>, infère le type réel de T si getClass() est une sous-classe directe et non-générique de C, en réfléchissant sur la clause EXTENDS de cette classe déclaration . (Si cette clause extends contenait cependant une autre variable de type comme dans class D<T> extends C<T>, la méthode lançait une exception ClassCastException lors de la tentative de conversion d'une variable de type en Class<?>).

S'il est possible de généraliser cet extrait pour tout getClass() direct ou non générique, mais si getClass() est générique, les informations limitées que l'exécution conserve sur les paramètres de type sont insuffisantes pour déterminer le type.

Questions connexes