10
votes

Java Generics Wildcard prolonge la classe finale

Pourquoi Java ne jette aucun avertissement lors de la compilation de mon TestGenerics , en considérant que la chaîne est final et ne peut pas être étendu? XXX


2 commentaires

Pourquoi pensez-vous que cela devrait?


@ L4zy quand j'ai essayé d'utiliser la méthode, j'ai obtenu un avertissement ... Allez également ceci lors de la compilation de Code source inabiletable - Type SM erroné:


3 Réponses :


6
votes

Le compilateur ne prend pas vraiment note de ce fait, car cela n'a pas d'importance. String CODE> S est toujours autorisé dans la liste et dans le produit final, la possibilité de tout ce qui s'étend chaîne code> est introuvable. Après Erasure , il ressort comme suit:

public void addStrings(List list)


3 commentaires

Par ce raisonnement, vous devriez pouvoir passer une liste à une méthode qui attend une liste d'une liste , car après effacement, ils sont tous les deux juste Liste . C'est certainement vrai du bytecode, mais l'ensemble des génériques est de fournir une sécurité de type au-dessus et au-delà quel code d'octet peut fournir.


Non, l'effacement ne supprime aucune information de type des signatures de méthode. En bytecode, la méthode aura une signature générique de "<: + ljava / lang / string;> (ljava / util / liste ;) v" ( ou quelque chose comme ça).


@ Rogério, je devrai vérifier cela



7
votes

Disons que j'avais une méthode comme celle-ci: XXX

accordé, pas la meilleure signature au monde, mais toujours parfaitement légal. Que se passerait-il si je passe une liste list à cette méthode? Selon la signature, il renvoie une liste . Si Java a rejeté ce type, il serait impossible d'utiliser cette méthode pour list (ou au moins, il serait impossible d'utiliser la valeur de retour).

Personnellement, la syntaxe est toujours utile dans ce cas, car Liste et Liste avoir des restrictions différentes - spécifiquement, vous ne pouvez rien ajouter d'autre qu'un null littéral à Liste . Je vais parfois utiliser ? Extend pour signifier qu'une collection est en lecture seule (car le seul t s S est null ) et ? Super pour signifier l'écriture de l'écriture uniquement (puisque vous ne pouvez obtenir que t S comme objet ). Ce n'est pas complètement absolu (vous pouvez toujours appeler Supprimer les méthodes, transmettre null S, Downcast, etc.) mais sert de rappel doux de la façon dont la collection est probablement utilisée. < / p>


4 commentaires

Il existe peut-être des cas d'utilisation pour renvoyer des listes génériques limitées comme celle-ci, mais je l'éviterais habituellement. Les objets renvoyés par une méthode laissent la zone encapsulée de leur classe et doivent être considérées comme la propriété de l'endroit appelé méthode. Si vous souhaitez donner un accès restreint à un retour de liste interne collections.unmodifiablelist () / avoir une méthode comme YourObject.addtointnallist (Somedata) . Qui applique une utilisation correcte et que vous pouvez Gardez des caractères génériques bornées hors de valeurs de retour .


@zaplace de style, je suppose. Si vous retournez un collections.unmodifiablelist , il n'y a rien à indiquer que dans la signature de type. Donc, maintenant je pourrais faire une copie de la liste, puis je vais obtenir un non pris en chargeOrexception lorsque j'essaie de le modifier - il négocie la verbosité d'un type de référence (sur le site d'appel) pour Tapez la sécurité. Ce serait bien si la JDK avait une superinterface de chaque classe de collection qui n'avait que des méthodes de lecture, mais cela ne le fait pas; Fondamentalement, je (parfois) utiliser la liste en tant que LISTLIST , puisque ce dernier n'existe pas.


Non visible au moment de la compilation est en effet problématique, vous devez compter sur les utilisateurs de lire votre documentation. ibler < / a> pourrait être une option bien que cela prend en charge l'élimination. Ou quelque chose comme de Guava's immutablelist qui a-t-il au moins dans le nom mais comme il s'agit d'une liste a .add () etc..


Si je voulais remplacer le type de vérification de type avec la documentation de Loosey-Goosey, j'utiliserais Python. ;)



0
votes

Le système de type ne considère pas list et list équivalent, même si au moment de la compilation, string n'a aucun sous-type autre que lui-même, donc tout objet qui est une liste doit également être une liste .

Une explication est que final n'est pas final - il est correct pour supprimer final d'une classe et rien ne devrait casser: http://docs.oracle.com/javase/specs/jls/se7/ HTML / JLS-13.HTML # JLS-13.4.2

Ce n'est pas sans précaution que le système de type prend final en examen; Par exemple, nous ne pouvons pas lancer une chaîne à un exécutable , car le compilateur figure si un objet est chaîne , il ne peut pas être une sous-classe inconnue cela implémente exécutable .

Si nous voulons que les génériques devaient aussi faire un raisonnement comme ça et déduire que list et liste équivalent, cela fera de taper des règles encore plus compliquées.


0 commentaires