0
    int test;

b.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent b){
        test = 1;
    }
});

How could I use this action listener to change test to 1 I know the code above doesn't work but what can I do?

  • Okay I just realized that it has void in the action Listener so that makes sense. – marty56 Jan 14 '20 at 00:45
  • 1
    What return type has to do with variable visibility? – PM 77-1 Jan 14 '20 at 00:46
  • 1
    [Change Variable from the inside of a ActionListener](https://stackoverflow.com/questions/34464541/change-variable-from-the-inside-of-a-actionlistener) is that what you want? – invzbl3 Jan 14 '20 at 02:05

2 Answers2

1

I'm afraid that you simply cannot do that.

Assuming that test is a local variable, the callback method is not permitted to change it.

Why?

Because by the time that the callback is called, the method that declared the test variable may have returned, meaning that the variable no longer exists. (The compiler complain that test should be read only in the listener method ... I think.)


Lets put this into a (hypothetical) context:

public class MyClass {
    Button b = ...

    public void myMethod() {
        int test = 0;

        b.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent b){
                test = 1;   // COMPILATION ERROR
            }
        });

        System.out.println("test is " + test);
    }
}

The intention here is to print "test is 1" when the button is clicked.

But this won't work. The problem is that addActionListener adds the listener method and returns immediately. The next thing that happens is that myMethod will try to print test. Even if this was legal Java (it isn't!) the value printed would be 0 ... not 1.

We could "fix" the compilation error by declaring test as an instance variable rather than a local variable.

public class MyClass {
    Button b = ...
    int test = 0;

    public void myMethod() {

        b.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent b){
                test = 1;   // OK now ...
            }
        });

        System.out.println("test is " + test);
    }
}

But the code still doesn't do what we want. The test variable will be printed too soon.

The thing you need to understand is that callbacks always happen later. If you want to see the change to test at the point of the println, then callbacks (listeners) are not the right way to implement things.


Summary: you have both a compilation error AND a conceptual problem in your example code.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • My intention is not to print it out its just to store it for later so if this changes it at the click of a button then it works because the only time I would use it would be at the click of another button so the instance variable should work. – marty56 Jan 14 '20 at 01:40
  • Then your mistake is storing it in a local variable. Because the local variable won't be there "later". – Stephen C Jan 14 '20 at 02:11
  • Yeah I realized that and changing it to an instance variable worked perfectly well for what I'm doing so thanks. – marty56 Jan 14 '20 at 02:56
0

You cannot access the variable unless they are final because this is the way Java manages closures.

private final MyClass test = new MyClass();

b.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent b){
        test.setMyInt(1);
    }
});

public class MyClass{
    int myInt;
    // getter/setter
}
Talha Ahmed Khan
  • 15,043
  • 10
  • 42
  • 49