D'après ce que j'ai lu: La raison en est qu'il n'est pas facile de déterminer quelle méthode sera appelée, car nous avons un héritage.
Cependant, pourquoi Java n’a-t-il pas au moins une optimisation de la récursion pour les méthodes statiques et n’impose pas le moyen approprié d’appeler des méthodes statiques avec le compilateur?
Pourquoi Java n'a-t-il aucun support pour la récursion de la queue?
Je ne suis pas sûr qu'il y ait une difficulté du tout.
En ce qui concerne le duplicata suggéré , comme l'explique Jörg W Mittag 1 :
- L'autre question concerne le coût total de possession, celui-ci concernant TRE. TRE est beaucoup plus simple que TCO.
- En outre, l’autre question concerne les limitations imposées par la machine virtuelle Java aux implémentations de langage souhaitant être compilées dans la machine virtuelle. Cette question concerne Java, qui est le seul langage qui n’est pas restreint par la machine virtuelle, dans la mesure où la spécification de la machine virtuelle peut être modifiée. les mêmes personnes qui conçoivent Java.
- Enfin, il n'y a même pas de restriction dans la JVM à propos de TRE, car celle-ci a un GOTO intra-méthode, qui est tout ce dont vous avez besoin pour TRE.
1 Formatage ajouté pour rappeler les points créés.
Réponses:
Comme l'explique Brian Goetz (architecte de langage Java chez Oracle) dans cette vidéo :
Tout ce qui modifierait le nombre d'images sur la pile briserait cela et provoquerait une erreur. Il admet que c'était une raison stupide, et les développeurs du JDK ont depuis remplacé ce mécanisme.
Il mentionne ensuite que ce n'est pas une priorité, mais que la récursion de la queue
NB: Ceci s'applique à HotSpot et à OpenJDK, les autres machines virtuelles peuvent varier.
la source
Java n’a pas l’optimisation des appels de queues pour la même raison que la plupart des langages impératifs ne l’ont pas. Les boucles impératives sont le style préféré du langage et le programmeur peut remplacer la récursion de la queue par des boucles impératives. La complexité n'en vaut pas la peine pour une fonctionnalité dont l'utilisation est découragée par une question de style.
Cette chose dans laquelle les programmeurs voulaient parfois écrire dans un style FP dans des langages sinon impératifs n’était à la mode que depuis une dizaine d’années, après que les ordinateurs ont commencé à s’intégrer dans des cœurs au lieu de GHz. Même maintenant, ce n'est pas si populaire. Si je proposais de remplacer une boucle impérative par une récursion de la queue au travail, la moitié des réviseurs de code riraient et l'autre moitié donnerait un regard confus. Même en programmation fonctionnelle, vous évitez généralement la récursion de la queue, à moins que d'autres constructions, telles que les fonctions d'ordre supérieur, ne s'emboîtent mal.
la source
for
boucle" (et de même pour les fonctions de première classe vs les objets). Je n'irais pas jusqu'à qualifier cela de "bigoterie impérative" mais je ne pense pas que cela aurait été très demandé en 1995 alors que la principale préoccupation était probablement la vitesse de Java et le manque de médicaments génériques.Java n’offre pas d’optimisation d’appel en hauteur, car la machine virtuelle Java n’a pas de code-octet pour les appels en aval (vers un pointeur de fonction inconnu , par exemple, une méthode dans une vtable).
Il semble que pour des raisons sociales (et peut-être techniques), l'ajout d'une nouvelle opération de code intermédiaire dans la machine virtuelle Java (ce qui la rendrait incompatible avec les versions précédentes de cette machine virtuelle) est terriblement difficile pour le propriétaire de la spécification de la machine virtuelle.
Les raisons techniques pour ne pas ajouter de nouveau bytecode dans les spécifications de la machine virtuelle Java incluent le fait que les implémentations réelles de la machine virtuelle Java sont des composants logiciels extrêmement complexes (en raison, par exemple, de nombreuses optimisations JIT).
Les appels en queue vers une fonction inconnue requièrent le remplacement du cadre de pile actuel par un nouveau et cette opération doit être effectuée dans la machine virtuelle (il ne s’agit pas uniquement de changer le compilateur générant du code intermédiaire).
la source
Sauf si une langue a une syntaxe spéciale pour effectuer un appel final (récursif ou autre) et qu'un compilateur craquera lorsqu'un appel final est demandé mais ne peut pas être généré, l'optimisation "optionnelle" de l'appel final ou de la récursion générera des situations dans lesquelles une pièce de code peut nécessiter moins de 100 octets de pile sur une machine, mais plus de 100 000 000 octets de pile sur une autre. Une telle différence devrait être considérée comme qualitative plutôt que simplement quantitative.
On s'attend à ce que les machines aient des tailles de pile différentes et il est donc toujours possible que le code fonctionne sur une machine, mais bloque la pile sur une autre. Cependant, en règle générale, le code qui fonctionne sur une machine même lorsque la pile est artificiellement restreinte fonctionnera probablement sur toutes les machines avec des tailles de pile "normales". Toutefois, si une méthode récurrente 1 000 000 de profondeur est optimisée en appel final sur une machine, mais pas sur une autre, l'exécution sur la première machine fonctionnera probablement même si sa pile est exceptionnellement petite et échouera sur cette dernière même si sa pile est exceptionnellement grande. .
la source
Je pense que la récursion d'appels en queue n'est pas utilisée en Java principalement parce que cela altérerait les traces de la pile et rendrait donc le débogage d'un programme beaucoup plus difficile. Je pense que l'un des principaux objectifs de Java est de permettre aux programmeurs de facilement déboguer leur code, et le traçage des piles est essentiel pour le faire, en particulier dans un environnement de programmation fortement orienté objet. Etant donné que l'itération pourrait être utilisée à la place, le comité de langue a dû se rendre compte qu'il ne valait pas la peine d'ajouter une récursion de la queue.
la source