
Envoyé par
Kikito
Je parle biensûr d'avoir rajouter cette fonction à la classe ArrayList, pourquoi ne serait-ce pas possible ? ton point 1 n'est pas gênant et pour ton point 2 le tableau utilisé en interne par l'ArrayList étant de type E :
Le type du tableau est déclaré en tant que type E[], mais en vérité il ne s'agit que d'un tableau d'objet Object[] comme tu peux le voir à l'initialisation :
this.elementData = (E[])new Object[initialCapacity];
Cela produit un warning car le cast vers (E[]) ne veut rien dire car E n'est pas connu à l'exécution, donc cela revient à écrire ceci :
this.elementData = (Object[])new Object[initialCapacity];
en déclarant elementData en tant que Object[].
Bref en interne ArrayList utilise un Object[] mais n'y ajoute que des objet du type E via la vérification à la compilation...
Ici le E[] sert avant tout à simplifier un peu le code et à limiter le nombre de cast...
Le problème c'est que pour retourner un tableau du bon type, il faut connaitre ce type à l'exécution (puisque le type des tableaux est vérifié à l'exécution). Or le type des generics est perdu (à l'exécution E est remplacé par Object avec des cast implicite).
Donc la méthode toArray() ne peut pas renvoyer le bon type de tableau car elle ne connait pas le type exact du paramétrage des générics, alors que la méthode toArray(T[]) possède cette information (le type du tableau en paramètre est récupéré).
Ce n'est donc pas possible.
A titre d'exemple essaye de coder la méthode suivante en renvoyant un tableau du bon type :
1 2 3 4 5 6 7
| class MyClass<E> {
public E[] createArray() {
return null;
}
} |
Tu verras que ce n'est pas possible tel quel.
Le seul moyen étant de spécifier le type de E en passant un objet de type Class en paramètre, par exemple :
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class MyClass<E> {
private final Class<E> type;
public MyClass(Class<E> type) {
this.type = type;
}
@SuppressWarnings("unchecked")
public E[] createArray() {
return (E[]) Array.newInstance(this.type, 5);
}
} |
Il faut utiliser du @SuppressWarnings pour la méthode Array.newInstance() qui n'est pas generic (parce qu'elle retourne un Object et non pas un Object[]), mais ca marche...
Par contre on est obligé de spécifier le type de E en paramètre du constructeur : cela aurait un impact énorme sur les codes existant si on devait faire cela avec les différentes collections...
Bref les Generics ont une implémentation particulière basé sur le type-erasure (effacement du type -- c'est à dire qu'à l'exécution on utilise le type de base et non pas le type spécifique comme avec d'autre langage), avec leurs défauts et leurs avantages : Les Generics ne sont pas des Templates comme les autres !
Toutefois, il existe une RFE pour "supprimer" le type-erasure des generics, ce qui pourrait permettre de faire des chose du tyle :
1 2 3
| public E[] createArray() {
return new E[5];
} |
http://bugs.sun.com/bugdatabase/view...bug_id=5098163
a++
Partager