Je sais que lorsqu'un compilateur Java compile un type générique, il effectue une effacement de type et supprime toutes les références au générique à partir du code et de mon Je ne suis pas intéressé par d'autres problèmes qui tapent des causes d'effacement, juste une réponse simple de quelqu'un qui comprennent mieux la JVM que moi. P> Je suis le plus intéressé par le coût Cet exemple: P> arraylist "p "La question que je n'ai pas de réponse claire est, que ce manque de type (et donc de coulée de type obligatoire) a ralentissement. Par mots, si j'utilise le compilateur Java standard et la norme JVM 1.7 de Oracle: P>
ArrayList code>, juste avec tout l'objet code> S tourné vers cheesecake S Aurais-je quelque chose (encore une hypothétique et je ne m'intéresse pas aux effets secondaires d'avoir un plus grand binaire en raison de plusieurs classes ni de la duplication de mon code). LI>
ul> CheesecakeList list = new CheesecakeList();
for (int i = 0; i < list.size(); i++)
{
//where the return of list.get() is a Cheesecake, therefore there is no casting.
list.get(i).eat(me);
}
4 Réponses :
La vérification de type est effectuée au moment de la compilation. Si vous faites cela:
List list = new ArrayList();
Je reçois cela, ce que je ne reçois pas, c'est combien de coût. Aussi, quand je fais ((fromesecake) list.get.get (0)). Mangez (moi) CODE> Est-ce que la distribution (qui pourrait / serait-elle probablement produite dans une boucle) significative
Je ne suis pas sûr de savoir quel est le coût (je devinerais zéro coût pour des moulues). Mais ce n'est certainement plus cher que objet O = nouveau entier (5); code>.
Même s'il y a un coût, il dépasse fortement les exceptions d'exécution que vous pourriez obtenir lorsqu'il n'utilise pas de génériques
Mais ce deuxième exemple est intéressant, car vous avez raison, qui a une couplage implicite. Je ne sais pas comment cela est traité.
L'envoi de la méthode virtuelle est susceptible de coûter plus cher. Tout est fortement optimisé. Un avantage de l'effacement des types d'exécution est que l'objet «générique» n'a pas besoin de transporter autant d'informations de type.
@ Jamesj.reganiv: Cependant, je pense que le coût réduit est inévitable. Parce que le compilateur / JVM ne sait pas si vous avez bas quelque chose de grim (mais parfaitement légal) comme: Liste
Mon Dieu Oli, j'ai rarement vu une ligne de code comme ça. Si certains le font dans le monde réel et l'enfer se déchaîne dans le service de soutien, c'est sur lui et son critique de code !!
@Tom: Bien sûr, c'est un exemple extrême;)
Mais je pense que pour votre exemple, vous devez expliquer explicitement une annotation pour ignorer les crashtypes qui donnent déjà un indice au développeur ... Je ne pense pas que le compilateur accepterait que tel quel.
La courte histoire: oui, il y a un chèque de type. Voici la preuve -
Compte tenu des classes suivantes: p> le bytecode que comme vous pouvez en décalage Cela encourage une pénalité d'exécution. Cependant, comme la JVM est assez bien optimisée, l'effet de cela est susceptible d'être minimal. P> L'histoire la plus longue: P> Comment allez-vous sur la mise en œuvre d'un tel Bottom Line: Ne pas optimiser prématurément. P> Un commentaire final. Les gens pensent souvent que l'effacement de type signifie que En d'autres termes, la classe a.main () code> est compilé (décompilé via Javap -c A.Class code>) est comme suit: p> 14 code>, le résultat de Cell.get () Code> est vérifié pour vérifier qui est en effet une chaîne: p> de la catégorie code> de cheesecakelist? Cette classe ne définirait-elle pas un tableau pour tenir les éléments? Soyez conseillé que chaque affectation à un tableau entraîne une typecheck cachée. Donc, vous ne gagnerez pas autant que vous le pensez (bien qu'il soit probable que votre programme effectuera plus d'opérations de lecture que des opérations d'écriture, un tableau code> cheesecak [] code> vous donnera quelque chose). P> cellule cellule Cell t code> a une liaison ultrapper (disons numéro code>), il est compilé dans cellule cellule mycell code> est de type cellule
"Bottom Line: Ne pas optimiser prématurément." I> Ceci. +1
C'était une question purement éducative. Mais votre ligne disant que le typacast est là et que la JVM gère très bien ces personnes, étaient les deux éléments principaux que je voulais obtenir de cette question.
Il convient également de noter que le chèque d'exécution est celui que la prédiction de la succursale du processeur va être capable de gérer très facilement, ce qui améliorera encore les performances.
Le bytecode comprend-il un type de coulé? p> blockQuote>
Oui. L'effacement de type est décrit brièvement dans Ce tutoriel P>
Si oui, incluent-il une vérification de temps d'exécution pour vérifier si c'est le type correct? P> blockQuote>
Non. La sécurité type est garantie à la hauteur de la compilation tant que vous n'avez pas d'avertissements. Cependant, il y a des méthodes de pont em> utilisés comme décrit dans le tutoriel ci-dessus p>
[
EDIT: STRUT> Pour clarifier "Non" signifie qu'il n'y a pas de contrôle d'exécution supplémentaire em> supplémentaire inséré par le compilateur en raison de l'utilisation de génériques. Toute vérification d'exécution lors du casting est toujours effectuée] p> La conversion elle-même prend-elle une quantité de temps non triviale? p> blockQuote>
Par conversion Voulez-vous dire le casting? Si oui, alors ce serait le cas même si vous n'aviez pas de génériques p>
ferait ma propre catégorie code> cheesecakelist code> identique à
ArrayList code>, ... p> blockQuote>En général, ce n'est pas une question simple à répondre et certainement pas sans prendre en compte d'autres facteurs. Tout d'abord, nous ne parlons plus de génériques. Vous demandez si une classe spécialisée serait plus rapide qu'une arraylist
code>. hypothétiquement em> Oui, avoir une classe spéciale qui éviterait le casting devrait être plus rapide. Mais la vraie question estsi vous êtes préoccupé par celui-ci strong>? p> Pour répondre à la dernière question que vous devez être spécifique. Chaque cas est différent. Par exemple, combien d'objets parlons-nous? Des millions? Appels répétés? Le temps supplémentaire est-il notable dans la performance du programme? Avez-vous chronométré? Comment nous attendons-nous que nos données se développent à l'avenir? etc etc p>
N'oubliez pas non plus que les compilateurs évoluent. Une version future peut avoir une optimisation qui corrigerait automatiquement un problème de performance (si vous pouvez vivre avec elle, c'est-à-dire), tandis que si vous collez avec une base de code qui devient inutile, il restera probablement avec le projet aussi longtemps que cela vit . p>
Donc, mon conseil est a) Soyez certain que vous avez un problème dans cette zone spécifique, sinon vous n'essayez pas de surperformer le compilateur ou la langue elle-même b) Temps de votre code, définissez certaines normes de ce que vous voulez atteindre (par exemple Combien de retard est acceptable, ce que je dois gagner, etc.), etc.), ne vous sentez que si vous êtes convaincu que vous êtes sur la bonne voie. Personne ne peut vous dire ça. p>
espoir que cela aide p>
Non. La sécurité de type est garantie au moment de la compilation tant que vous n'avez pas d'avertissements. Code> Ce n'est pas du point de vue de la JVM, la JVM doit donc vérifier au moment de l'exécution. La JVM ne sait pas si cette distribution provenait d'un générique bien vérifié, un générique non sécurisé (avertissements supprimé), une forme brute ou une personne écrivant par un bytecode dans un éditeur Hex. Cela ne sait pas et doit donc supposer que la sécurité de type n'est pas garantie.
@yshavit hmmm je ne suis pas sûr de ce que tu veux dire. Tant que vous n'avez pas d'avertissements au moment de la compilation, le compilateur s'est assuré que tous les types génériques sont bien vérifiés. La JVM n'a que besoin de prendre toutes les actions qu'il prend dans un scénario de distribution habituel. Il n'a pas besoin d'effectuer un chèque supplémentaire
Le JVM ne sait rien à propos de la langue Java. Tout ce qu'il sait sur le bytecode. De plus, il est nécessaire de lancer un classcastexception code> chaque fois qu'un casting inapproprié est effectué. Sauf s'il ne peut prouver que la distribution fonctionnera sur la base du bytecode (et cela peut le faire, je ne suis pas sûr - mais cela n'aurait pas à voir avec la sécurité de la compilation, car ces informations ont été effacées au moment de la compilation. ), il doit vérifier au moment de l'exécution.
@yshavit Je pense que je comprends votre objection. Vous vous référez au chèque d'exécution effectué pendant la fonte pendant que je parle de tout contrôle supplémentaire i> causé par la consommation de génériques. Je suis d'accord bien que ce ne soit pas clair, lequel des deux cas que l'OP surveille. Je mettrai à jour ma réponse pour clarifier que
Si vous avez suivi le code source JDK pour qui dit, une opération de contrôle code> code> est extrêmement rapide, surtout si vous vérifiez un objet qui est de la classe nommée et non d'une sous-classe. La présence est probablement plus importante pour une optimisation du JITC légèrement bouleversante que pour le coût d'exécution réel. P> ArrayList CODE>, et que vous l'avez cloné dans CHEESECAKELIST CODE> et modifié tous les occurrences code> d'objet code> dans ArrayList CODE> TO CHESECAKE CODE>, le résultat (en supposant que vous l'avez fait correctement) serait une classe que vous pouvez utiliser dans votre application et nécessiter une opération de contrôle code> moins code>, vs Utilisation de ArrayList