Problème de casting avec les ArrayList

Résolu/Fermé
Pumbaa - 13 déc. 2007 à 12:02
ouechTonton Messages postés 13 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 13 novembre 2011 - 23 févr. 2011 à 15:52
Bonjour, j'ai un gros problème, j'essaye de faire une méthode générique qui clone en profondeur une ArrayList (donc qui clone chaque objet, pas seulement la liste elle-même) mais je n'arrive pas à le faire "proprement".

Voici une partie de mon programme :

/* L'interface */
public interface MyClonable
{
public MyClonable myClone();
}

/* La classe qui implémente l'interface */
public class Process implements MyClonable
{
public Process(Process source)
{
/* bla bla */
}

public Process myClone()
{
return new Process(this);
}
}

/* La méthode de clonage proprement dite */
public class Tools
{
public static ArrayList<MyClonable> deepClone(ArrayList<MyClonable> source)
{
ArrayList<MyClonable> clone = new ArrayList<MyClonable>(source.size());

for(MyClonable o:source)
clone.add(o.myClone());

return clone;
}
}

/* L'utilisation */
ArrayList<MyClonable> listSource = {...}; // Elle est déjà pleine
ArrayList<Process> listProcess = Tools.deepClone(listSource);
/* Problème : le compilateur me retourne : "The method deepClone(ArrayList<MyClonable>) in the type Tools is not applicable for the
arguments (ArrayList<Process>)"*/


Et je ne comprends pas du tout pourquoi. Avec un pote nous avons essayé de nombreuses idées, mais rien ne marche.
De tête nous avons testé :
- un casting : ArrayList<Process> listProcess = Tools.deepClone((ArrayList<MyClonable>)listProcess); --> Erreur, impossible de caster
- définir autrement le prototype de la méthode de clonage : public static ArrayList<? extends MyClonable> deepClone(ArrayList<? extends MyClonable> source) --> Erreur, Type mismatch: cannot convert from ArrayList<capture#1-of ? extends MyClonable> to
ArrayList<Process>
- plein d'autres trucs.

Le seul qui marche, c'est de ne mettre nul part le type de la collection : public static ArrayList deepClone(ArrayList source)
mais ça me met des warning partout (dans le prototype de la fonction, et dans son appel.
Auriez-vous une solution plus belle svp ?

D'avance merci


Pumbaa

7 réponses

Pumbaa Messages postés 15 Date d'inscription jeudi 13 décembre 2007 Statut Membre Dernière intervention 5 mai 2010 6
13 déc. 2007 à 20:49
Je me permet un "up" ^^
1
ouechTonton Messages postés 13 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 13 novembre 2011 1
23 févr. 2011 à 15:52
J'ai trouvé ceci comme explication et solution : http://tutorials.jenkov.com/java-generics/wildcards.html


En résumé, il faut écrire ce genre de code, avec des wildcards "?" :

public void test( ArrayList<? extends ClasseMere> argument) {
//Ton code

}

pour appeler cette méthode :
ArrayList<ClasseFille> liste;
test(liste);


Je ne connaissais pas ces wildcards. Je ne sais pas ce que les puristes en pense... mais j'achète !
1
Pumbaa Messages postés 15 Date d'inscription jeudi 13 décembre 2007 Statut Membre Dernière intervention 5 mai 2010 6
15 déc. 2007 à 11:13
Il n'y a vraiment aucun génie qui n'aurait une idée ? :-s
0
C'est pour moi une abberation dans Java qui vient de me gêner également. Le problème est le suivant: Il est impossible de caster directement ArrayList<B> vers ArrayList<A> même si A est une super-classe ou une interface de B.

Pour pouvoir faire la conversion, il faut le faire en 2 étapes en passant par une ArrayList générique.
Tu n'est pas obligé d'utiliser une ArrayList générique partout, mais tu ne sauras pas éviter d'avoir un warning lors de la double conversion...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Mouarf, au moins je ne suis pas le seul ^^

J'espère que ce "bug" sera fixé un jour, car comme tu le dis c'est un peu aberrant (à moins qu'on ne soit passé à côté de quelque chose...)
0
C'est un peu tard pour répondre mais comme je suis tombé sur ce topic en cherchant à caster une liste ça peut servir à quelqu'un d'autre.
Si on a accès au code source de la fonction qui prend une liste générique en paramètre on peut faire comme ça :

public <T extends ClasseMere> T test(List<T> l) {
return l.get(0);
}

pour appeler cette méthode :
List<ClasseFille> l = ...;
ClasseFille x = test(l); // ça marche, pas besoin de caster ni la liste ni le résultat
0
Il n'est jamais trop tard pour répondre ^^

Concernant ta solution, je ne comprends pas très bien. Aurais-tu l'amabilité de développer un petit peu stp ?
Par exemple, il manque le type à retourner dans ta fonction test, si j'ai bien compris.
0