2 votes

Confusion de la compilation Java : pourquoi ce code compile-t-il ?

Je ne suis pas sûr de la raison pour laquelle ce code (qui donne un stackoverflow au moment de l'exécution) compile :

import java.io.*;
import java.util.*;

public class StackOverflow {
   StackOverflow overflow = new StackOverflow();

   public void myCall() {
       overflow.myPrint();
   }

   public static void main(String[] args) {
       StackOverflow newStackOverflow = new StackOverflow();
       newStackOverflow.myCall();
   }

   public void myPrint() {
       System.out.println("I am confused!");
   }
}

La raison pour laquelle je suis confus est que, dans la définition de la classe, j'essaie de créer un objet de la classe que j'essaie de définir. Ne devrait-il pas s'agir d'une erreur de compilation ?

5voto

Makoto Points 23751

Ce n'est pas une erreur de compilation parce que le compilateur ne peut pas dire s'il va être généré à l'infini au moment de la compilation.

Vous et moi pouvons regarder cela et le voir avec certitude, mais le compilateur ne se soucie que de l'exactitude des déclarations. Il n'y a rien syntaxiquement illégale à propos de cette déclaration, c'est pourquoi le compilateur laissera faire.

C'est lié à la problème de l'arrêt en ce sens qu'un programme ne peut pas dire s'il va s'arrêter avec succès.

1voto

Ted Hopp Points 122617

On pourrait argumenter, je suppose, que le compilateur devrait attraper cette version récursive d'une boucle infinie, mais il n'y a rien dans la définition du langage qui rend illégal pour un objet de construire une autre instance de lui-même lors de son instanciation.

C'est certainement quelque chose que je m'attendais à ce que les outils d'analyse de code comme FindBugs pour se plaindre.

0voto

Will Hartung Points 57465

Non, ce n'est pas un problème avec Java. Il est assez rapide et lâche sur les déclarations dynamiques et n'a pas besoin d'avoir des choses déclarées avant qu'elles ne soient utilisées. Tout est résolu plus tard, et cela rend le langage un peu plus facile à utiliser.

0voto

joshuahealy Points 3289

Il vous donne une exception de débordement de pile parce que chaque fois que vous créez un StackOverflow, la ligne

StackOverflow overflow = new StackOverflow();

Crée un autre StackOverflow, qui en crée un autre, et ainsi de suite jusqu'à ce que la pile atteigne son maximum et lève une exception.

0voto

Thilo Points 108673

Non. Java ne fait rien pour détecter les boucles infinies ou les récursions infinies au moment de la compilation. Vous pouvez compiler un code comme le vôtre ou la méthode ci-dessous sans problème, il explosera au moment de l'exécution.

 private int recurseForever(){
     return recurseForever();
 }

Dans votre cas, le constructeur crée une nouvelle instance de la classe et appelle donc un autre constructeur et ainsi de suite.

Quant à savoir pourquoi elle ne le fait pas : Parce qu'il est impossible de le faire pour tous les cas (problème d'arrêt), et que jeter des ressources sur une solution partielle (qui ne fonctionne que parfois, mais rend la compilation plus lente en permanence et pour tout le monde, en introduisant peut-être aussi des bogues parce que le compilateur est plus compliqué maintenant) n'a apparemment pas été considéré comme une bonne idée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X