2011-08-24 48 views
2

我有一个用Java编写的应用程序。我有3个类mysql_query,tablesetup,table_action。现在在每个类的类中,我创建了其他类的对象,这会导致递归对象调用。我可以用什么方法来解决这个问题?Java中的StackOverflow异常

例如:

在mysql_query.java我有

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

在tablesetup.java我有

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

类似地,在table_action.java我有

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

- EDIT-- 传递一个类对象到其他构造函数不会在我的情况下锻炼,因为我有很多像这样的依赖类。那么通常程序员如何安排这些类?我可以使用interface吗?在这种情况下使用是否合适?

+0

似乎所有3类实例,另2作为属性。这是你的意图吗? –

回答

7
  • tablesetup你实例在table_action一个table_action
  • 你实例化一个tablesetup

我猜你看到的循环 - 第一个创建第二的新实例,这将创建一个新的实例第一个,创建第​​二个的新实例,依此类推,直到你的堆栈(持有方法和构造函数调用)被填充。

稍微澄清一点 - 当你通过构造函数实例化一个对象时,它的所有字段都被初始化。因此,当您实例化table_action时,将调用new tablesetup()以初始化tablesetuptablesetup变量。

循环依赖不是一件好事,但你可以拥有它们。创建table_action时,您只需传递对现有tablesetup的引用即可。

除此之外 - 你没有使用正确的java命名。你不应该使用小写类和下划线。专有名称是TableSetup,TableActionMySQLQuery。除大写外,变量名也一样。他们应该由mysqlQuerytableSetup

+0

只是nitpick,我更喜欢MySqlQuery :) –

+0

对于那个,我最喜欢的例子是'HttpURLConnection'。去图.. – Bozho

+0

@Bozho:我了解tat概念..谢谢你。我想知道这个问题的解决方案。检查我的编辑! – Deepak

2

这种问题的一种解决方案称为延迟初始化。正确地初始化对象可能是一项非常复杂的任务。一般来说,你应该避免在构造函数中初始化太多的其他对象(或者隐式构造函数,就像你的情况一样)。这里有一个例子:

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; 
    } 
} 

我不能告诉你,如果上面是要正常工作,但它会给你懒初始化的想法。

UPDATE:在您编辑之后,我的回答将不足以满足您的使用案例。您可能想要在专用工厂的外部管理对象的生命周期。请参阅此处工厂模式的基本说明:http://en.wikipedia.org/wiki/Factory_method_pattern

处理模型对象的复杂生命周期的另一种方法是使用框架,如EMF:http://www.eclipse.org/modeling/emf/。 EMF帮助您在Java中正确建模1:1,1:nm:n关系,正确处理/维护双向引用。我不知道这是否会矫枉过正你,虽然......

+0

这是* one *的解决方案。请注意,它要求对象是可变的,这在某些情况下并不理想。另外,这意味着'tablesetup'不会引用创建它的同一个table_action,除非将它传递给构造函数(这会返回类似的问题)。 –

+0

也许不是。但“不变的初始化”似乎太复杂,无法解释手头的问题。关于“几个参考”,OP的问题已经是这种情况。我猜想,手头的物品并不真正拥有自己的状态。 –

+0

@Lukas Eder:我必须在同一个文件的许多地方使用类对象。我认为在这种情况下,懒惰初始化并不合适。检查我的编辑..你怎么看? – Deepak

2

您只能创建一个实例,然后把它传递给别人这样的:

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

感谢。检查我的编辑并告诉我你的想法! – Deepak

3

Bozho已经显示出失败的原因,但对于解决方案,有多种选择:

  • 打破循环引用;为什么每个班级都需要参考另一个班级?
  • 使一类的“大师”,并使其构造通this到构造为其他类:

    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; 
        } 
    } 
    

    这样做的缺点是:

    • 的依赖仍然相当紧张
    • 你让this逃离Foo的构造函数;通常一个物体在完成构建之前不应该公布它的存在。
  • 使类可变的,并且具有创建所有这些没有他们的依赖单独的方法,然后设置依赖事后

+0

@Joh Skeet:谢谢你的回复。我在编辑中解释了我的问题。你对那个怎么想的 ? – Deepak