2011-08-24 4 views
2

J'ai une application qui est écrite en Java. J'ai 3 classes mysql_query, tablesetup, table_action. Maintenant, à l'intérieur de la classe de chacun de la classe, j'ai créé l'objet d'autres classes qui se traduit par un appel d'objet récursif. Quelles sont les alternatives que je peux utiliser pour résoudre ce problème?Exception StackOverflow en Java

Par exemple:

En mysql_query.java j'ai

 
public class mysql_query{ 
    tablesetup tablesetup = new tablesetup(); 
    table_action table_action = new table_action(); 
} 

En tablesetup.java je

 
public class tablesetup{ 
    mysql_query mysql_query= new mysql_query(); 
    table_action table_action = new table_action(); 
} 

De même dans table_action.java Je

 
public class table_action{ 
    mysql_query mysql_query= new mysql_query(); 
    tablesetup tablesetup= new tablesetup(); 
} 

--EDIT-- en passant un objet de classe au constructeur de l'autre ne fonctionnera pas dans mon cas car j'ai beaucoup de classes dépendantes comme ça. Alors, habituellement, comment les programmeurs organisent ces classes? Puis-je utiliser interface? Est-il approprié d'utiliser dans ce cas?

+0

Il semble tous les 3 classes instancier les 2 autres que les propriétés . Est-ce votre intention? –

Répondre

7
  • dans tablesetup vous instancier un table_action
  • dans table_action vous êtes instanciation d'une tablesetup

Je suppose que vous voyez la boucle - le premier crée une nouvelle instance de la seconde, ce qui crée une nouvelle instance de la première, qui crée une nouvelle instance de la seconde, et ainsi de suite jusqu'à ce que votre pile (méthode de maintien et appels du constructeur) soit remplie. Un peu plus de précisions - lorsque vous instanciez un objet à travers son constructeur, tous ses champs sont initialisés. Ainsi, lorsque vous instanciez table_action, new tablesetup() est appelée pour initialiser la variable tablesetuptablesetup.

Les dépendances circulaires ne sont pas une bonne chose, mais vous pouvez les avoir. Vous avez juste besoin de passer une référence à un tablesetup existant lors de la création table_action s. En dehors de cela - vous n'utilisez pas le nommage Java approprié. Vous ne devez pas utiliser de classes minuscules et de traits de soulignement. Les noms propres sont TableSetup, TableAction et MySQLQuery. Il en va de même pour les noms de variables, mis à part les majuscules. Ils devraient par mysqlQuery, tableSetup, etc

+0

juste pour nitpick, je préfère MySqlQuery :) –

+0

Pour celui-là, mon exemple préféré est 'HttpURLConnection'. Va comprendre .. – Bozho

+0

@Bozho: J'ai compris le concept de tat ... merci pour ça. Je veux connaître la solution à ce problème. Vérifiez ma modification !! – Deepak

2

Une solution à ce genre de problème est appelée initialisation paresseux. Une initialisation correcte des objets peut être une tâche très complexe. En général, vous devriez éviter d'initialiser trop d'autres objets dans le constructeur (ou le constructeur implicite comme dans votre cas). Voici un exemple:

public class table_action{ 
    // Never access members directly: 
    private mysql_query mysql_query; 
    private tablesetup tablesetup; 

    // Only access getters 
    mysql_query get_mysql_query() { 
    if (mysql_query == null) { 
     mysql_query = new mysql_query(); 
    } 
    return mysql_query; 
    } 

    tablesetup get_tablesetup() { 
    if (tablesetup == null) { 
     tablesetup = new tablesetup(); 
    } 
    return tablesetup; 
    } 
} 

Je ne peux pas vous dire si ce qui précède va fonctionner correctement, mais il vous donnera une idée sur l'initialisation paresseuse.

MISE À JOUR: Après votre modification, ma réponse ne sera pas suffisante pour votre cas d'utilisation. Vous voudrez peut-être gérer le cycle de vie de vos objets de manière externe dans une usine dédiée. Voir une explication de base sur le modèle d'usine ici: http://en.wikipedia.org/wiki/Factory_method_pattern.

Une autre façon de gérer le cycle de vie complexe des objets du modèle consiste à utiliser des structures telles que EMF: http://www.eclipse.org/modeling/emf/. EMF vous aide à modéliser correctement les relations 1:1, 1:n et m:n en Java, en manipulant/maintenant correctement les références bidirectionnelles. Je ne sais pas si ce sera trop pour vous, mais ...

+0

Voilà * une * solution à cela. Notez qu'il faut que les objets soient mutables, ce qui n'est pas idéal dans certains cas. Cela signifie également que 'tablesetup' n'aura pas de référence à la même table_action que celle qui l'a créée, sauf si vous le passez dans le constructeur (ce qui revient à des problèmes similaires). –

+0

Peut-être pas. Mais «l'initialisation immuable» semble trop complexe à expliquer pour la question posée. A propos de "plusieurs références", c'est déjà le cas dans la question du PO. Je devine que les objets à portée de main n'ont pas vraiment leur propre état. –

+0

@Lukas Eder: Je dois utiliser l'objet de classe à plusieurs endroits dans le même fichier. Je pense que dans ce cas, l'initialisation paresseuse n'est pas appropriée. vérifier mon édition .. qu'en pensez-vous? – Deepak

2

Vous pouvez créer une seule instance et passer ensuite à d'autres comme celui-ci:

public class mysql_query{ 
    tablesetup tablesetup; 
    table_action table_action; 
    public void mysql_query() { 
    tablesetup tablesetup = new tablesetup(this); 
    table_action table_action = new table_action(this); 
    } 
} 

public class tablesetup{ 
    mysql_query mysql_query; 
    table_action table_action; 
    public void tablesetup(mysql_query query) { 
    mysql_query = query; 
    table_action = new table_action(this); 
    } 
} 

public class table_action{ 
    mysql_query mysql_query; 
    tablesetup tablesetup; 
    public void table_action(mysql_query query, tablesetup setup) { 
     mysql_query = query; 
     tablesetup = setup; 
    } 
} 
+0

Merci pour votre réponse. Vérifiez ma modification et dites-moi ce que vous en pensez !! – Deepak

3

Bozho a montré pourquoi il échoue , mais pour une solution, il existe différentes options:

  • Briser les références circulaires; Pourquoi chaque classe a-t-elle besoin d'une référence à l'autre?
  • Faire une classe « maître » et de faire passer son constructeur this dans le constructeur de l'autre classe:

    class Foo 
    { 
        private final Bar bar; 
    
        public Foo() 
        { 
         bar = new Bar(this); 
        } 
    } 
    
    class Bar 
    { 
        private final Foo foo; 
    
        public Bar(Foo foo) 
        { 
         this.foo = foo; 
        } 
    } 
    

    Les inconvénients de cette situation sont:

    • Les dépendances sont encore assez serré Vous laissez this échapper du constructeur Foo; Habituellement, un objet ne doit pas publier son existence tant qu'il n'a pas été construit.
  • Faites vos cours mutable et une méthode distincte qui crée tous sans leurs dépendances, puis définit les dépendances après,

+0

@Joh Skeet: Merci pour votre réponse. J'ai expliqué mon problème dans mon édition. Que penses-tu de cela ? – Deepak

Questions connexes