Problème de casting avec les ArrayList
Résolu
Pumbaa
-
ouechTonton Messages postés 13 Date d'inscription Statut Membre Dernière intervention -
ouechTonton Messages postés 13 Date d'inscription Statut Membre Dernière intervention -
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
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
A voir également:
- Problème de casting avec les ArrayList
- [C#] ArrayList - Forum C#
- Casting - Forum Cinéma / Télé
- Recherche de casting - Forum Cinéma / Télé
- Casting-merlin - Forum Loisirs / Divertissements
- Casting fr ✓ - Forum Consommation & Internet
7 réponses
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 !
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 !
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...
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...
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...)
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...)
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
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