web-dev-qa-db-fra.com

Comment convertir les types de liste génériques en java?

Eh bien, j'ai une classe client (pas de classe de base).

Je dois lancer de LinkedList à List. Y a-t-il une manière propre de faire ceci?

Juste pour que vous sachiez, je dois le jeter dans List. Aucun autre type ne fera l'affaire. (Je développe un appareil de test avec Slim et FitNesse).


EDIT: OK, je pense que je dois donner des exemples de code ici.

import Java.util.*;
public class CustomerCollection
{
    protected LinkedList<Customer> theList;

    public CustomerCollection()
    {
        theList = new LinkedList<Customer>();
    }

    public void addCustomer(Customer c){ theList.add(c); }
    public List<Object> getList()
    {
        return (List<? extends Object>) theList;
    }
}

Donc, conformément aux remarques de Yuval A, j'ai finalement écrit le code de cette façon. Mais je reçois cette erreur:

CustomerCollection.Java:31: incompatible types
found   : Java.util.List<capture#824 of ? extends Java.lang.Object>
required: Java.util.List<Java.lang.Object>
        return (List<? extends Object>)theList;
               ^
1 error

Alors, quelle est la bonne façon de faire ce casting?

13
jrharshath

Vous n'avez pas besoin de lancer. LinkedList implémente List afin que vous n'ayez pas de choix à faire ici.

Même si vous souhaitez sous-traiter une List de Objects, vous pouvez le faire avec des génériques comme dans le code suivant:

LinkedList<E> ll = someList;
List<? extends Object> l = ll; // perfectly fine, no casting needed

Maintenant, après votre édition, je comprends ce que vous essayez de faire, et c’est quelque chose d’impossible, sans créer une nouvelle List comme ceci:

LinkedList<E> ll = someList;
List<Object> l = new LinkedList<Object>();
for (E e : ll) {
    l.add((Object) e); // need to cast each object specifically
}

et je vais expliquer pourquoi ce n'est pas possible autrement. Considère ceci:

LinkedList<String> ll = new LinkedList<String>();
List<Object> l = ll; // ERROR, but suppose this was possible
l.add((Object) new Integer(5)); // now what? How is an int a String???

Pour plus d'informations, reportez-vous au didacticiel sur les génériques de Sun Java . J'espère que cela clarifie.

28
Yuval Adam

Voici mon horrible solution pour le casting. Je sais, je sais, je ne devrais pas relâcher quelque chose de ce genre dans la nature, mais cela s’est avéré utile pour lancer un objet sur n’importe quel type:

public class UnsafeCastUtil {

    private UnsafeCastUtil(){ /* not instatiable */}

    /**
    * Warning! Using this method is a sin against the gods of programming!
    */
    @SuppressWarnings("unchecked")
    public static <T> T cast(Object o){
        return (T)o;
    }

}

Usage:

Cat c = new Cat();
Dog d = UnsafeCastUtil.cast(c);

Maintenant je vais prier les dieux de programmer mes péchés ...

19
logan

J'ai fait cette fonction pour ça, moche mais ça marche

public static <T> Collection<T> cast(Collection<? super T> collection, Class<T> clazz){
    return (Collection<T>)collection;
}
2
julman99
>    public List<Object> getList()

Pourquoi retournez-vous List <Object>? Vous pouvez aussi bien renvoyer List (sans génériques) car c'est équivalent, mais cela ferait fonctionner le code suivant: 

LinkedList<Customer> theList = new LinkedList<Customer>();

public List getList() {
    return theList;
}

La diffusion entre des listes de types génériques différents est délicate et semble inutile ici.

Bien sûr, vous devriez retourner le type List <Client> ...

1
Kris

viens de mettre

public static List<Object> getList() {
    List l = test;
    return l;
}
0
Ravi Parekh

Si votre liste est d'un type générique, par exemple

ArrayList<String> strList = new ArrayList<String>(); strList.add("String1"); Object o = strList;

alors la méthode suivante devrait fonctionner

public <T> List<T> getListObjectInBodyOfType(Class<T> classz, Object body) {
    if(body instanceof List<?>){
        List<?> tempList = (List<?>)body;
        if(tempList.size() > 0 && tempList.get(0).getClass().equals(classz)){
            return (List<T>) body;
        }
    }
    return new ArrayList<T>();
}

Comment l'utiliser?

List<String> strList1 = getListObjectInBodyOfType(String.class, o);

comme je l'ai mentionné précédemment, cela fonctionne si l'Object contient une liste générique, cela ne fonctionnera pas si vous passez une liste non générique avec un type mixte d'éléments

0
Vishal

Vous devriez renvoyer un List<?> à partir de votre méthode. Intuitivement, getList() renvoie une liste afin que l'appelant puisse récupérer les éléments qu'il contient. List<?> (qui équivaut à List<? extends Object>) permet cette fonctionnalité. Cependant, vous ne pourrez rien y insérer via la liste retournée, car cela ne serait pas sûr; mais je ne pense pas que ce soit ce dont vous avez besoin de toute façon.

public List<?> getList()
{
    return theList;
}
0
newacct

LinkedList implémente List, vous pouvez donc implémenter

List< String > list1 = new LinkedList< String >(); 

Ou souhaitez-vous diffuser de LinkedList <String> vers List <int>? dans ce cas, vous devez sélectionner chaque élément et le convertir en entier.

0
Markus Lausberg