Java中的StackOverflow异常

时间:2011-08-24 07:27:07

标签: java stack-overflow

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

例如:

在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吗?在这种情况下使用是否合适?

4 个答案:

答案 0 :(得分:7)

  • tablesetup中您正在实例化table_action
  • table_action中您正在实例化tablesetup

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

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

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

除此之外 - 您没有使用正确的Java命名。您不应该使用小写类和下划线。专有名称为TableSetupTableActionMySQLQuery。变量名也是如此,除了大写。它们应该mysqlQuerytableSetup

答案 1 :(得分:3)

Bozho已经证明了它失败的原因,但对于解决方案,有各种选择:

  • 打破循环引用;为什么每个班级都需要引用另一个?
  • 将一个类设为“master”,并使其构造函数将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;
        }
    }
    

    这样做的缺点是:

    • 依赖关系仍然非常紧张
    • 你让thisFoo构造函数中逃脱;通常,一个对象在构建完成之前不应该发布它的存在。
  • 让你的类可变,并有一个单独的方法创建所有没有它们的依赖项,然后设置依赖项

答案 2 :(得分: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;
   }
}

我无法告诉你上述内容是否能够正常工作,但它会让你对懒惰的初始化有所了解。

更新:编辑完成后,我的回答将不足以满足您的使用需求。您可能希望在专用工厂外部管理对象的生命周期。请在此处查看有关工厂模式的基本说明:http://en.wikipedia.org/wiki/Factory_method_pattern

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

答案 3 :(得分: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;
   }
}