Reputation: 6802
I have an application which is written in Java. I have 3 classes mysql_query, tablesetup, table_action. Now inside the class of each of the class I have created the object of other classes which results in recursive object invocation. What are the alternative that I can use to fix this problem ?
For Example:
In mysql_query.java i have
public class mysql_query{ tablesetup tablesetup = new tablesetup(); table_action table_action = new table_action(); }
In tablesetup.java I have
public class tablesetup{ mysql_query mysql_query= new mysql_query(); table_action table_action = new table_action(); }
Similarly in table_action.java I have
public class table_action{ mysql_query mysql_query= new mysql_query(); tablesetup tablesetup= new tablesetup(); }
--EDIT--
passing one class object to the constructor of other will not workout in my case as I have many dependent classes like this. So usually how programmers arrange these classes ? Can I use interface
? Is it appropriate to use in this case ?
Upvotes: 2
Views: 1773
Reputation: 220762
One solution to this sort of problem is called lazy initialisation. Correct initialisation of objects can be a very complex task. In general you should avoid initialising too many other objects in the constructor (or implicit constructor as in your case). Here's an example:
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;
}
}
I can't tell you if the above is going to work correctly, but it will give you an idea about lazy initialisation.
UPDATE: After your edit, my answer won't be sufficient for your use case. You might want to manage the lifecycle of your objects externally in a dedicated factory. See a basic explanation on the factory pattern here: http://en.wikipedia.org/wiki/Factory_method_pattern.
Another way of handling the complex lifecycle of model objects is by using frameworks such as EMF: http://www.eclipse.org/modeling/emf/. EMF helps you correctly model 1:1
, 1:n
and m:n
relationships in Java, correctly handling/maintaining bi-directional references. I don't know if that will be overkill for you, though...
Upvotes: 2
Reputation: 59158
You can create only one instance and then pass it on to others like this:
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;
}
}
Upvotes: 2
Reputation: 1499860
Bozho has shown why it fails, but for a solution, there are various options:
Make one class the "master" and make its constructor pass this
into the constructor for the other class:
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;
}
}
The downsides of this are:
this
escape from the Foo
constructor; usually an object shouldn't publish its existence until it has finished being constructed.Make your classes mutable, and have a separate method which creates all of them without their dependencies, then sets the dependencies afterwards
Upvotes: 3
Reputation: 597026
tablesetup
you are instantiating a table_action
table_action
you are instantiating a tablesetup
I guess you see the loop - the first creates a new instance of the second which creates a new instance of the first, which creates a new instance of the second, and so on until your stack (holding method and constructor calls) is filled.
A little more clarification - when you instantiate an object through its constructor, all of its fields are initialized. So when you instantiate table_action
, new tablesetup()
is invoked in order to initialize the tablesetuptablesetup
variable.
Circular dependencies are not a good thing, but you can have them. You just need to pass a reference to an existing tablesetup
when creating table_action
s.
Apart from that - you are not using proper java naming. You should not use lowercase classes and underscores. The proper names are TableSetup
, TableAction
and MySQLQuery
. Same goes for variable names, apart from the upper-case. They should by mysqlQuery
, tableSetup
, etc.
Upvotes: 7