Combinaison de types bruts et de méthodes génériques

Voici une question, cette première liste de code comstack très bien (JDK 1.6 | JDK 1.7):

ArrayList a = new ArrayList(); Ssortingng[] s = a.toArray(new Ssortingng[0]); 

Toutefois, si je déclare la référence à la List tant que type brut:

 ArrayList a = new ArrayList(); Ssortingng[] s = a.toArray(new Ssortingng[0]); 

Je reçois une erreur du compilateur disant que la Ssortingng[] est requirejse mais que l’ Object[] été trouvé.

Cela signifie que mon compilateur interprète la méthode générique comme renvoyant Object[] malgré la réception d’un Ssortingng[] tant qu’argument.

J’ai double vérifié la signature de la méthode toArray(myArray) :

  T[] toArray(T[] a); 

Il s’agit donc d’une méthode paramétrée dont le paramètre de type n’a aucune relation avec celui de la liste (c.-à-d. ).

Je ne sais pas du tout en quoi l’utilisation d’un type brut affecte l’évaluation des méthodes paramétrées à l’aide de parameters de type indépendants.

  • Quelqu’un at-il une idée pourquoi ce code ne comstack pas?
  • Est-ce que quelqu’un connaît des références où ce comportement est documenté?

Ce n’est pas exactement ce à quoi vous vous attendiez, mais si vous vous référez à une classe générique sous forme brute, vous perdez la possibilité d’utiliser des génériques de quelque manière que ce soit pour les membres de l’exemple. Ce n’est pas limité aux méthodes génériques non plus, regardez ceci:

  public class MyContainer { public List ssortingngs() { return Arrays.asList("a", "b"); } } MyContainer container = new MyContainer(); List ssortingngs = container.ssortingngs(); //gives unchecked warning! 

C’est la partie pertinente du JLS ( 4.8 ):

Le type de constructeur (§8.8), méthode d’instance (§8.4, §9.4), ou champ non statique (§8.3) M d’un type brut C qui n’est pas hérité de ses super-classes ou super-interfaces est le type brut correspondant. l’effacement de son type dans la déclaration générique correspondant à C.

Lorsque vous n’utilisez pas de génériques, le compilateur le traite comme un type brut. Chaque type générique devient donc Object et vous ne pouvez donc pas transmettre Ssortingng[] car il a besoin de Object[]
Alors voici l’affaire – Si vous utilisez

 List l = new ArrayList(); 

Vous utilisez le type brut et tous ses membres d’instance sont remplacés par ses homologues d’effacement. En particulier, chaque type paramétré apparaissant dans une déclaration de méthode d’instance est remplacé par son équivalent brut. Voir JLS 4.8 pour plus de détails.

C’est la description la plus proche que j’ai trouvée dans la spécification pour décrire ce comportement observé:

Le type d’un constructeur (§8.8), d’une méthode d’instance (§8.8, §9.4), ou d’un champ non-statique (§8.3) M d’un type brut C qui n’est pas hérité de ses super-classes ou super-interfaces est l’effacement de son type dans la déclaration générique correspondant à C. Le type d’un membre statique d’un type brut C est le même que son type dans la déclaration générique correspondant à C.

Le fait de transmettre des parameters de type réels à un membre de type non statique d’un type brut qui n’est pas hérité de ses superclasses ou de ses superinterfaces est une erreur de compilation.

D’après ce qui précède et le comportement observé, je pense qu’il est prudent de dire que tous les types de parameters génériques sont supprimés d’un type brut. Bien sûr, l’utilisation de types bruts eux-mêmes est déconseillée dans le code non hérité:

L’utilisation de types bruts est autorisée uniquement en tant que concession à la compatibilité du code hérité. L’utilisation de types bruts dans le code écrit après l’introduction de la généricité dans le langage de programmation Java est fortement déconseillée. Il est possible que les futures versions du langage de programmation Java interdisent l’utilisation de types bruts .

Il peut être intéressant de noter que ce comportement peut être “résolu”. Utilisez deux interfaces, une interface de base non générique et une interface générique. Ensuite, le compilateur sait que toutes les fonctions de l’interface de base non générique ne sont pas génériques et les traitera de cette manière.

Ce comportement est très gênant si vous utilisez des stream et un chaînage de fonctions et je le résous donc comme suit.

Soution via l’inheritance d’interface :

 public interface GenericInterface extends BaseInterface { X getValue(); } public interface BaseInterface { Ssortingng getSsortingngValue(); } 

Maintenant vous pouvez faire ce qui suit sans avertissement ni problème:

 GenericInterface object = ...; Ssortingng ssortingngValue = object.getSsortingngValue(); 

Il ne peut y avoir aucun paramètre de type passé dans la méthode toArray () puisque votre ArrayList est une liste non paramésortingsée, il sait seulement qu’il contient des objects, c’est tout. a.toArray() retournera toujours un tableau Object []. De nouveau, vous devez le convertir en (Ssortingng[]) (avec tous les dangers qu’il contient) si vous souhaitez spécifier qu’il contient le type de chaîne spécifique.