Search code examples
javaswingstack-overflow

Java, StackOverflowError when extending a class, or instantiating


Okay, at first, I know why I am getting this error, but just don't how to solve it.

I have a couple classes, a main class, a layout class and a buttonClick class.

The problem is in the buttonClick class: I have some variables in my layout class that I have to use in my buttonClick class.

This is my Layout class:

public class Layout extends JPanel {
    public JButton BTN_werpen;

    public Layout{
        BTN_werpen = new JButton("Werpen");
        BTN_werpen.setBounds(465, 10, 80, 30);
        BTN_werpen.addActionListener(new WerpButton());
        P_velden.add(BTN_werpen);
    }

Of course, this is not the full class, but it's everything you need to know.

The I have my 'WerpButton' actionListner class:

public class WerpButton extends Layout implements ActionListener {
    BTN_werpen.setEnabled(false);
}

Again, this is not everything, but it already fails when I just use the code here. And I know why it fails: that's because when the Layout class gets extended the constructor gets called and it will create a new object, which triggers the WerpButton class what then calls the Layout class, and so on. It basically becomes a loop.

Now, my question is:

How do I solve this problem?

I've tried a lot already, like not extending it but just use Layout layout = new Layout(); And then using layout.BTN_werpen in my code, but that does not work too.


Solution

  • public class WerpButton extends Layout
    

    So, you create new WerpButton() essentially called new Layout()

    public Layout() {
        ...
        BTN_werpen.addActionListener(new WerpButton());
        ...
    }
    

    Which again called new WerpButton... and the loop repeats


    Why does an ActionListener have the name anything-"Button"? (unless implemented on the button class itself, of course).

    In other words, why does did you implement ActionListener on a Layout?

    Did you mean to extend JButton instead of Layout?

    public class WerpButton extends JButton implements ActionListener {
        public WerpButton() {
            this.addActionListener(this);
        }
    
        @Override
        public void onActionPerformed(ActionEvent e) {
            this.setEnabled(false);
        }
    }
    

    Besides, this would not have worked if you had a separate class file

    public class WerpButton extends Layout implements ActionListener {
        BTN_werpen.setEnabled(false); // 'BTN_werpen' can't be resolved. 
    }
    

    You can try doing it the other way - the layout implements the listener. That way you do not need a separate class strictly to handle button events.

    public class Layout extends JPanel implements ActionListener {
        public JButton BTN_werpen;
    
        public Layout() {
            BTN_werpen = new JButton("Werpen");
            BTN_werpen.setBounds(465, 10, 80, 30);
            BTN_werpen.addActionListener(this);
            P_velden.add(BTN_werpen);
        }
    
        @Override
        public void onActionPerformed(ActionEvent e) {
            if (e.getSource() == BTN_werpen) {
                // handle click
                BTN_werpen.setEnabled(false);
            }
        }