web-dev-qa-db-fra.com

Comment corriger "L'expression de type List nécessite une conversion non contrôlée ... '?

Dans l'extrait Java:

SyndFeedInput fr = new SyndFeedInput();
SyndFeed sf = fr.build(new XmlReader(myInputStream));
List<SyndEntry> entries = sf.getEntries();

la dernière ligne génère l'avertissement

"L’expression de type List nécessite une conversion non contrôlée pour se conformer à List<SyndEntry> "

Quel est un moyen approprié pour résoudre ce problème?

128
user46277

Puisque getEntries renvoie un List brut, il peut contenir n'importe quoi.

L'approche sans avertissement consiste à créer un nouveau List<SyndEntry>, Puis convertissez chaque élément du résultat sf.getEntries() en SyndEntry avant de l'ajouter à votre nouvelle liste. Collections.checkedList Fait pas effectue cette vérification pour vous - bien qu'il aurait été possible de l'implémenter pour le faire.

En effectuant votre propre conversion, vous "respectez les conditions de garantie" de Java génériques: si un ClassCastException est généré, il sera associé à un transfert dans le code source, pas une distribution invisible insérée par le compilateur.

94
erickson

Il s'agit d'un problème courant lorsque vous utilisez des API antérieures à Java 5. Pour automatiser le solution de erickson , vous pouvez créer la méthode générique suivante:

public static <T> List<T> castList(Class<? extends T> clazz, Collection<?> c) {
    List<T> r = new ArrayList<T>(c.size());
    for(Object o: c)
      r.add(clazz.cast(o));
    return r;
}

Cela vous permet de faire:

List<SyndEntry> entries = castList(SyndEntry.class, sf.getEntries());

Comme cette solution vérifie que les éléments ont bien le bon type d’élément au moyen d’un transtypage, elle est sûre et ne nécessite pas SuppressWarnings.

111
Bruno De Fraine

Il semble que SyndFeed n'utilise pas de génériques.

Vous pouvez avoir une conversion non sécurisée et une suppression d'avertissement:

@SuppressWarnings("unchecked")
List<SyndEntry> entries = (List<SyndEntry>) sf.getEntries();

ou appelez Collections.checkedList - bien que vous ayez toujours besoin de supprimer l'avertissement:

@SuppressWarnings("unchecked")
List<SyndEntry> entries = Collections.checkedList(sf.getEntries(), SyndEntry.class);
25
Jon Skeet

Avez-vous écrit le SyndFeed?

Est-ce que sf.getEntries Renvoie la liste ou List<SyndEntry>? Je suppose que cela retourne List et que le changer pour retourner List<SyndEntry> Résoudra le problème.

Si SyndFeed fait partie d'une bibliothèque, je ne pense pas que vous puissiez supprimer l'avertissement sans ajouter l'annotation @SuppressWarning("unchecked") à votre méthode.

7
Alex B

Si vous utilisez Guava et que vous ne voulez que faire, parcourez vos valeurs:

for(SyndEntry entry: Iterables.filter(sf.getEntries(), SyndEntry.class){
  ...
}

Si vous avez besoin d’une liste réelle, vous pouvez utiliser

List<SyndEntry> list = Lists.newArrayList(
    Iterables.filter(sf.getEntries(), SyndEntry.class));

ou

List<SyndEntry> list = ImmutableList.copyOf(
    Iterables.filter(sf.getEntries(), SyndEntry.class));
2
Joseph K. Strauss

Si vous regardez le javadoc pour la classe SyndFeed (je suppose que vous faites référence à la classe com.Sun.syndication.feed.synd.SyndFeed), la méthode getEntries () ne renvoie pas Java.util.List<SyndEntry>, mais retourne juste Java.util.List.

Donc, vous avez besoin d'un casting explicite pour cela.

1
Shyam
SyndFeedInput fr = new SyndFeedInput();
SyndFeed sf = fr.build(new XmlReader(myInputStream));
List<?> entries = sf.getEntries();
1
Honglonglong

Si vous ne voulez pas mettre @SuppressWarning ("décoché") sur chaque appel sf.getEntries (), vous pouvez toujours créer un wrapper qui retournera List.

Voir cette autre question

0
Boune

Encore plus facile

return new ArrayList<?>(getResultOfHibernateCallback(...))

0
DennisTemper