0

I'm relatively new to Java and I'm coding extensions/plugins for online game Minecraft.

I've recently started "bigger" projects which require more classes to preserve neatness. I am still trying to fully understand how constructors work, but most recent try resulted into Stack Overflow (one constructor calling another, in loop).

In my case, for example, I have two classes, Main and MySQL.

Main class initializes plugin, MySQL class contacts database and returns data to any class which calls it.

Example problematic code:

Main.java

class Main extends JavaPlugin {

    private final MySQL mysql = new MySQL();

    //Method which is called first 
    void onEnable(){

        //Just an example of initializing
        mysql.init();
        mysql.open();
    }
}

MySQL.java

class MySQL {

    private final Main main = new Main();

    void init(){}
    void open(){}
}

I know what the problem is, I just don't know proper solution, which would work with even more classes.

Also if I would have another class, main would connect to MySQL, another class would communicate with it, I should do something like main.mysql.method ?

Simplified, easy to understand explanation on how constructors and instances ("new" keyword) work would be much appreciated. Thanks in advance !

ShiiNko
  • 25
  • 2
  • 8

2 Answers2

1

First of all, just as a pointer for future applications, you might want to take a look at Design Patterns, they tend to make design cleaner and easier to maintain.

In your case you have created a Circular Reference. The easiest way to get around it would be to make something like so:

class Main extends JavaPlugin {

    private final MySQL mysql;

    public Main(MySQL mysql)
    {
        this.mysql = mysql
    }

    //Class which is called first 
    void onEnable() {

        //Just an example of initializing
        mysql.init();
        mysql.open();
    }
}

class MySQL {

    private final Main main = new Main(this);

    void init(){}
    void open(){}
}

This should solve the problem.

That being said, I am assuming that the MySQL class will have database related mechanisms. Such mechanisms are usually exposed through a Singleton design pattern. This design pattern should allow you to access the methods within the MySQL class only when you need them, thus also avoiding the circular reference issue.

maba
  • 47,113
  • 10
  • 108
  • 118
npinti
  • 51,780
  • 5
  • 72
  • 96
  • Thanks for an answer, however does _private final MySQL mysql;_ call MySQL class which than initializes _mysql_ variable ? – ShiiNko Aug 09 '12 at 09:57
  • That won't work if `Main` is the literal top-level entry point, which very often must have a constructor without arguments. Fixing `MySQL` seems easier to me. – Volker Stolz Aug 09 '12 at 09:57
  • Thanks to both of you, I've been doing this before, I just thought there's easier way. Anyway, thanks. – ShiiNko Aug 09 '12 at 10:02
  • @user1587051: The variable is initialized within the constructor. Final variables can only be assigned once, but should allow you to declare it and assign it at a later stage. – npinti Aug 09 '12 at 10:02
  • @ShiDoiSi: Yes I do agree. I just did it that way to get the point to the OP. – npinti Aug 09 '12 at 10:03
0

The field mysql must get instantiated every time an object of type Main is created. When a new MySQL instance is created, since it has the field Main main, a new Main instance is created. 20 goto 10 :-)

In the MySQL class, you can avoid creating another Main instance in two ways: either make sure that you refer to static members of Main, or make MySQL a nested class within Main, in which case you don't need the extra field.

Volker Stolz
  • 7,274
  • 1
  • 32
  • 50