C'est vrai, mais ils auraient pu renvoyer un tableau de type apparent T[]... (T[]) tab;Citation:
Envoyé par adiGuba
On est sûr que tous les éléments sont de type T donc c pas génant...
Version imprimable
C'est vrai, mais ils auraient pu renvoyer un tableau de type apparent T[]... (T[]) tab;Citation:
Envoyé par adiGuba
On est sûr que tous les éléments sont de type T donc c pas génant...
Sauf que comme on ne connait pas le type exact de T, on ne peut pas instancier de tableau de T et l'instruction suivante provoque une erreur :Citation:
Envoyé par ®om
a++Code:return new T[5];
Bah, oui, mais cette instruction, non:Citation:
Envoyé par adiGuba
Code:T[] tab = (T[]) new Object[5];
Non car le type des tableaux est vérifié à l'exécution. Et qu'un Object[] ne peut pas être casté en String[] par exemple...Citation:
Envoyé par ®om
Si tu prend le code suivant :
Tu verras que tu obtiens une ClassCastException à l'execution...Code:
1
2
3
4
5
6
7
8
9
10
11 class Test<T> { public T[] toArray() { return (T[]) new Object[5]; } public static void main(String[] args) { Test<String> test = new Test<String>(); String[] strings = test.toArray(); } }
Note toutefois que le compilateur te préviens en générant un warning sur l'instruction suivante :
Code:(T[]) new Object[5]
La seule solution pour renvoyer un tableau du bon type est d'avoir un objet Class du bon type, par exemple :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 class Test<T> { private final Class<T> type; public Test(Class<T> type) { assert type!=null; this.type = type; } @SuppressWarnings("unchecked") public T[] toArray() { return (T[]) Array.newInstance(this.type, 5); } public static void main(String[] args) { Test<String> test = new Test<String>(String.class); String[] strings = test.toArray(); } }
a++
Ah ouais, étonnant, car ce code:
pourrait générer un warning à la compilation... Pourtant, ça n'est qu'à l'exécution que ça plante...Code:
1
2 Object[] o = new Object[5]; String[] s = (String[]) o;
C'est "normal" : les tableaux possèdent une notion d'héritage (String[] hérite de Object[]) qui fait que la vérification ne peut être effectué qu'à l'exécution.Citation:
Envoyé par ®om
Il n'y a pas de warning car l'utilisation des casts est par nature non-sécurisé et peut potentiellement provoquer une ClassCastException à l'exécution. Ton exemple est toutefois un cas simple qu'un outil de vérification de code pourrait détecter... mais ce n'est pas toujours aussi simple, par exemple :
Car dans ce cas on ne peut pas prédir d'éventuelle erreur cast sans analyser le code de la méthode, car si le vrai type du tableau est String[] cela fonctionnera. Le code suivant ne pose pas de problème :Code:
1
2 Object[] o = uneMethodeQuiRenvoitUnTableau(); String[] s = (String[]) o;
Code:
1
2 Object[] o = new String[5]; String[] s = (String[]) o;
A l'inverse les Generics sont sécurisé et provoqueront plusieurs warnings/erreurs pour éviter ce type de problème : un code qui utilise les Generics ne devrait pas provoquer de ClassCastException s'il compile sans erreur ni warning...
Par contre un warning sur l'utilisation des Generics peut impliquer l'apparition de ClassCastException plus loin dans le code !!!!
D'ailleur les Generics apportent tellement de nouveaux warnings qu'il est parfois impossible de compiler un code 100% sécurisé sans warning si on n'utilise pas l'annotation @SuppressWarning...
a++
Surtout si on mélange Generics / non Generics (par exemple quand on fait du Swing qui n'est pas générique...)Citation:
Envoyé par adiGuba
En effet... mais il faut quand même rester prudent, bien comprendre la raison du warning, et limiter au minimum sa portée avant d'utiliser l'annotation @SuppressWarning...Citation:
Envoyé par ®om
a++