Comment puis-je convertir à partir de la liste & lt;? & Gt; à la liste & lt; T & gt; en Java en utilisant des génériques?
En Java, comment puis-je convertir des List<?>
à List<T>
à l'aide d'une méthode usage général, de sorte que je peux remplacer des modèles comme la suivante avec un seul appel de méthode:
List untypedList = new ArrayList(); //or returned from a legacy method
List<Integer> typedList = new ArrayList<Integer>();
for (Object item: untypedList)
typedList.add((Integer)item);
Noter que le code ci-dessus ne permet pas de générer n'importe quel type-avertissements de sécurité et, idéalement, votre solution ne devrait pas générer de tels avertissements, soit.
Sera la solution suivante travail à condition que la liste Class<L>
dispose d'un constructeur par défaut?
public class ListUtil {
public static <T, L extends List<T>> L typedList(List<?> untypedList, Class<T> itemClass, Class<L> listClass) {
L list = null;
try {
list = listClass.newInstance();
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
for (Object item: untypedList)
list.add(itemClass.cast(item));
return list;
}
}
(Notez que listClass.newInstance()
jette InstantiationException
ou IllegalAccessException
si une instance de Class<L>
ne pas avoir un public de constructeur par défaut. Quels sont les problèmes qui peuvent survenir si la méthode ne permet pas de gérer correctement ces exceptions?)
Notes:
T
est le type de chaque élément dans la liste.L
est le type de la liste que je souhaite créer (qui s'étend àList<T>
).untypedList
est le "non typé" liste d'entrée, effectivement la même queList<Object>
.itemClass
représente la classe d'exécution deT
.listClass
représente la classe d'exécution deL
.
source d'informationauteur Derek Mahar
Vous devez vous connecter pour publier un commentaire.
Plutôt que de passer dans le type de la liste que vous souhaitez instancier, pourquoi ne pas simplement passer dans le vide de la Collection de<T> que vous voulez peuplée? Ainsi, les utilisateurs de votre api beaucoup plus de souplesse, en utilisant le constructeur par défaut n'est pas toujours idéal. (par exemple, peut-être que je veux un Jeu où je donne le nombre d'éléments, ou des je veux une liste triée où je donne le Comparateur).
Aussi, comme une note de côté, vous devez toujours programme pour la plupart des interface générique possible. Dans ce cas, votre entrée devez être rien de plus précis qu'un objet iterable, et de la sortie d'une Collection.
Compte tenu de cela, je voudrais écrire la méthode de cette façon -
puis le code d'appel qui ressemble à:
2 Commentaires ici:
Je voudrais utiliser Goyave et ses Iterables.filtre(Itératif,la Classe) méthode avec une méthode de fabrique de la
Lists
classe, comme suit:Ce sera effectivement vérifier chaque objet dans la liste d'origine, et la liste ne contient que les éléments qui sont des instances d'un type donné (
String
dans ce cas) ou un sous-type. Je ne pense vraiment pas qu'il est logique de demander aux utilisateurs de fournir unClass
pour la suite de laList
type et essayer de les instancier par la réflexion.Vous avez un problème d'exécution de sorte qu'il doit être indépendant des génériques. Au moment de l'exécution, everyting "est un Objet" de toute façon. Si vous ne pouvez pas instancier
listClass
alors vous avez réellement passer à une mise en œuvre dejava.util.List
qui n'offre pas (public) constructeur vide.Donc la solution à votre problème est en dehors de cette méthode. L'appelant comme
ne devrait pas donner un erreur à l'exécution.
Maintenant, j'ai mon éclipse à la main. Le code suivant compile et, pas de mises en garde et répondre à vos exigences: convertir un non liste pour une liste tapée.
De goyave à nouveau, mais permet plus de contrôle sur la conversion si ses plus complexe qu'un plâtre ou d'autres joyeusetés.
La
de la Classe.newInstance()
méthode jette deux checked exceptionsIllegalAccessException
etInstantiationException
. Ceux-ci doivent être pris ou déclarées dans la signature de la méthode de votre méthode.Pour l'enregistrement, ces exceptions sont jetés dans une variété de situations; par exemple,
C'est en fait sans lien avec le fait que la méthode est générique, et le typage des questions.
Je ne crois pas que ce que vous essayez de faire est possible. C'est parce que des Génériques de travail:
Au moment de la compilation entrant tous les types d'une liste tapée sont vérifiés et tous les objets sont projetées pour le type de la liste - et à partir de ce moment là, nous parlons d'un non "liste". Les génériques sont tout sucre syntaxique, malheureusement.
Que voulez-vous atteindre? Exemple de code:
fonctionne, tout simplement. Il génère de l'avertissement, mais il fonctionne. Toutefois, il est possible que dans
li
vous aurez des objets qui ne sont pas des instances deInteger
. Si vous voulez être sûr, utiliser google goyave, comme ColinD répondu.S'il vous plaît ne pas utiliser des réflexions de ce genre de choses!
Je le traiter comme un cas d'une transformation. Peut-être quelque chose comme
L'utilisation d'une usine de
List<>
si vous le souhaitez.Si vous ne voulez pas l'avertissement, et vous ne voulez pas utiliser google goyave, vous avez à mettre en place quelque chose de similaire à la goyave vous-même. E. g.:
Cette mise en œuvre juste ommits éléments qui ne sont pas des instances de T, mais vous pouvez tout aussi bien jeter l'exception, ou n'importe quoi d'autre que vous voulez.