J'ai écrit une fois cette méthode:
private <T> SortedSet<T> createSortedSet() {
return new TreeSet<T>();
}
Il est censé être appelé comme ceci:
Set<String> set = createSortedSet();
Cela fonctionne bien (bien que j'aie vu dans les réponses ici lors de la recherche de la question actuelle que cela est sujet aux erreurs).
Quoi qu'il en soit, j'écris maintenant le code suivant (dans une classe qui étend javax.servlet.jsp.tagext.TagSupport):
private <T> T evaluate(String expression) {
ExpressionEvaluator evaluator = pageContext.getExpressionEvaluator();
return evaluator.evaluate(expression, T, null, pageContext.getVariableResolver());
}
Le but est de pouvoir appeler ça comme:
Integer width = evaluate(widthStr);
Le code de ma méthode d'évaluation ne fonctionne évidemment pas. Le deuxième argument de evaluator.evaluate()
est censé être un objet Class. Cela m'amène à:
Comment puis-je obtenir la classe d'un type générique (retour)? Que dois-je écrire à la place de T comme deuxième argument à évaluer?
Nicolas semble avoir raison, cela ne peut pas être fait et je dois passer la classe comme argument à ma méthode. L'avantage est que, puisque sa solution rend l'argument paramétré sur le type générique, j'obtiens un contrôle de compilation sur cet argument.
Malheureusement, vous devrez certainement changer votre méthode pour:
private <T> T evaluate(Class<T> clazz, String expression)
puis passez clazz
comme deuxième paramètre. Pas aussi court que prévu.
Vous pouvez d'abord créer un objet générique puis récupérer son type paramétré:
private <T> T evaluate(String expression) {
List<T> dummy = new ArrayList<>(0);
Type[] actualTypeArguments = ((ParameterizedType) dummy.getClass().getGenericSuperclass()).getActualTypeArguments();
Type clazz = actualTypeArguments[0];
Class<T> theClass = (Class<T>) clazz.getClass();
ExpressionEvaluator evaluator = pageContext.getExpressionEvaluator();
return evaluator.evaluate(expression, theClass, null, pageContext.getVariableResolver());
}
Il faut se méfier! Vous n'avez pas de Class<>
objet, vous obtenez un objet de sous-classe TypeVariableImpl
, qui peut se comporter différemment.