List n’est pas égal à List ?

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.