5

When trying to adopt the style of implementing a listener using anonymous or nested class in order to hide the notification methods for other uses than listening (i.e. I don't want anybody to be able to call actionPerformed). For example from java action listener: implements vs anonymous class:

public MyClass() {
    myButton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            //doSomething
        }
    });
}

The question is if theres an elegant way to remove the listener again using this idiom? I figured out that the instantiation of ActionListener does not produce equal objects every time so Collection.remove() won't remove the originally added object.

In order to be considered equal the listeners should have the same outer this. To implement equals I would need to get hold of outer this for the other object. So it will go something like this (which I find a little bit clumpsy):

interface MyListener {
    Object getOuter();
}

abstract class MyActionListener extends ActionListener
    implement MyListener {
}

public MyClass() {
    myButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // doSomething on MyClass.this
        }
        public Object getOuter() {
           return MyClass.this;
        }
        public boolean equals(Object other)
        {
           if( other instanceof MyListener )
           {
              return getOuter() == other.getOuter();
           }
           return super.equals(other);
        });
    }
 }

Or will I be forced to keep the ActionListener object as a (private) member of the outer class?

Community
  • 1
  • 1
skyking
  • 13,817
  • 1
  • 35
  • 57
  • You can make those objects equal by overriding `equals()` in anonymous class, no? – Alex Salauyou Apr 29 '15 at 12:03
  • Why can't you use removeActionListener? – Chetan Kinger Apr 29 '15 at 12:15
  • removeActionListener depends on the object being removed compares equal with the object being supplied to removeActionListener. I've edited the question with explaination why I think implementing equals() will imply some overhead. – skyking May 04 '15 at 06:56

2 Answers2

4

Assign your anonymous listener to a private local variable, e.g.

public MyClass() {
    private Button myButton = new Button();
    private ActionListener actionListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            //doSomething
        }
    };
    private initialize() {
        myButton.addActionListener(actionListener);
    }
}

Later you can use the private variable actionListener to remove it again.

Uwe Plonus
  • 9,803
  • 4
  • 41
  • 48
  • Although this is not the answer I wished for, but it looks that one need to resort to assign the listener to a local variable. – skyking May 22 '15 at 07:35
4

Well that's the beauty of anonymous classes - they're anonymous :-)

No, there's no similarly elegant idiom to remove the listener again. The only way is to iterate through getActionListeners() and remove the one you want. Of course, if there is only one it's as easy as:

myButton.removeActionListener( myButton.getActionListeners()[ 0 ] );

which is not too ugly.

Necreaux
  • 9,451
  • 7
  • 26
  • 43
Anders R. Bystrup
  • 15,729
  • 10
  • 59
  • 55