Jetez un coup d’œil à cet exemple simple de génériques Java:
class List { T head; List next; } class A { List l; public int length() { List l = this.l; int c = 1; while (l.next != null) { c++; l = l.next; } return c; } public static void main(Ssortingng[] args) { A a = new A(); al = new List(); alhead = 123; alnext = new List(); alnext.head = 432; System.out.println("list length: " + a.length()); } }
Il se produit une erreur lors de la compilation, affirmant que les types sont incompatibles, tout en affirmant que les deux variables sont du même type:
$ javac A.java && java A A.java:10: incompatible types found : List required: List List l = this.l; ^ 1 error
Si je change la première ligne de length () en List l = (List)(Object)this.l;
, Ça marche. Pourquoi?
Vous avez déclaré une méthode générique dans une classe générique avec cette ligne:
public int length() {
Ce
est différent du
de votre classe. Selon la section 6.3 de JLS :
La scope du paramètre de type d’une classe (§ 8.1.2) est la section de paramètre de type de la déclaration de classe, la section de paramètre de type de toute superclasse ou superinterface de la déclaration de classe et le corps de la classe.
Vous n’avez pas besoin de re-déclarer
sur votre méthode; le paramètre de type de la classe est déjà dans la scope.
Pour utiliser le paramètre de type générique de votre classe
, demandez à votre méthode de ne pas déclarer un autre
et d’utiliser simplement le
votre classe:
public int length() {
Pour comprendre pourquoi votre casting fonctionne:
List l = (List )(Object)this.l;
Vous pouvez convertir n’importe quel object en Object
. Ensuite, vous lancez le résultat dans List
. Vous pouvez toujours le lancer comme bon vous semble. Java ClassCastException
simplement une ClassCastException
au moment de l’exécution si ce n’est pas vraiment une List
au moment de l’exécution. Mais le compilateur avertira également qu’il utilise des opérations non contrôlées ou non sécurisées, car il ne peut pas garantir que ce
est le
.
Pour illustrer la différence entre les
, vous pouvez utiliser comme paramètre de type générique pour la méthode et obtenir les mêmes résultats:
public int length() { List l = (List)(Object)this.l;
Ceci comstack avec le même type d’avertissement de sécurité.
Si vous savez vraiment que la sécurité de type peut être garantie, vous pouvez utiliser @SuppressWarnings("unchecked")
pour annoter votre méthode. Mais ici, je choisirais toujours de supprimer entièrement le paramètre de type générique de la méthode et d’utiliser le paramètre de type de la classe.