Search code examples
javaclassconstructorinstances

How to properly connect classes (Stack overflow in constructors)


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 !


Solution

  • 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.