Link to home
Start Free TrialLog in
Avatar of HanRui
HanRui

asked on

anonymous ActionListener


I can (??)  write the code to create an anonymous ActionListener:

myButton.addActionListener(new ActionListener() {actionPerformed (ActionEvent ae) {
              ...})

I don't understand the ActionListener(). There is no constructor method in the ActionListener interface. So how or why does this work?
Avatar of yongsing
yongsing

The ActionListener interface has only one method called actionPerformed(). To implement this interface, you only need to write the code for this method:

class MyFrame extends JFrame implements ActionListener
{
   public MyFrame
   {
      JButton myButton = new JButton("My Button");
      myButton.addActionListener(this);
      // other stuff...
   }
   public void actionPerformed(ActionEvent actionEvent)
   {
      // do something here
   }
}

An anonymous class is so called because it does not have a name and there is no named variable that holds a reference to it. Notice the thing about the anonymous class declaration:

class MyFrame extends JFrame
{
   public MyFrame
   {
      JButton myButton = new JButton("My Button");
      myButton.addActionListener(
         new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
                // do something here
            }
         }
      );
      // other stuff...
   }
}

It uses the name of an interface, ActionListener, where a named class would have a class name and "implements ActionListener". In this case, the anonymous extends Object by default and the compiler supplies the necessary code. The syntax new ActionListener() {...} indicates to the compiler that the code between the braces defines an anonymous class. This new class is not named, but it is automatically instantiated when this expression is executed. Because this anonymous inner class is defined within the scope of MyFrame, it has access to all the instance variables and methods within the scope of the class.
ASKER CERTIFIED SOLUTION
Avatar of k.jones
k.jones

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of HanRui

ASKER

Ok. I'm getting closer to understanding this. I looked that the API for 1.1 at Sun, and it does show the ActionListener as being implemented by the AWTEventMulticaster, which is a subclass of Object. I was taught at Sun that there is always a call to the superclass constructor method by default inside a class constructor method as the first line of executable code. Since there is no constructor method in ActionListener interface, there is no executable code to call the superclass constructor method, which is Object(). I was looking for ActionListener() as a constructor method somewhere, but it must not exist. There must be a default call to the Object() constructor method somewhere in the anonymous ActionListener code. At least my mind wants to think that way...
PS - in short, the compiler figures out what the constructor should look like and builds it.
PPS - After seeing your last comment, I believe that my comments provide the answer that you sought.
Avatar of HanRui

ASKER


I understand this to mean that the following line:

add(new Label("Here is it!"));

does not have an explicit constructor expression. But it does have a constructor method...
Label(String).

I don't find the same method in ... new ActionListener()...
When you write new Label("Here is it!") you are declaring an instance of the class Label. This is different from new ActionListener() {...}. For this one, you are declaring an anonymous class.
Avatar of HanRui

ASKER

I disagree. There is no declaration of Label, only the constructor method Label(String). The compiler must provide a dafault name.
What do you mean that there is no declaration for Label? The Label class is one of the AWT class that comes with the API. When you write add(new Label("Here is it!")), you are instantiating an instance of the class Label and passing the reference to the add() method. Here you are only using the Label class, not extending its capability.

This is different from new Label() {...}. For this one, you are creating (and instantiating) a new class by extending the Label class. Inside the {...}, you can override the non-private methods in Label to change its behaviour.
Avatar of HanRui

ASKER


Label myLabel; is my understanding of an explicit declaration.

public class MyLabel extends Label { ... creates a new class. I disagree with you that new Label() {...} is creating a new class.

The ... add(new Label("Hello"));  doesn't show an explicit declaration of a potential instance of the Label class. That's what I meant.. The compiler assigns a default name to the nameless instantiation and adds that instance to the container. The compiler creates the default name, and puts the name on the stack. Then it is instantiated. That's what I was at taught at Sun, anyway...



Of course new Label() {...} is creating a new class. It is an anonymous class so it doesn't have a name. If you don't believe, try this in your code: Suppose that you have a Frame called MyFrame, and you add a label to it:

add(new Label("My Label") { } );

With this statement, you are defining a new class by extending the class Label. Here, we did not override any of the methods in Label. When you compile your code, you will notice that you have one additional file in your system: MyFrame$1.class. This file contains the definition of your new class. An anonymous class does not have a name, and the compiler will assign a number to it starting with 1.

Of course, for our anonymous class, it isn't very useful because we are not changing the behaviour of its superclass Label. Now suppose that you want to add one label, and for just this label, you want its background color to be yellow. You can do this:

add(new Label("My Label")
{
   public Color getBackground()
   {
      return Color.yellow;
   }
}
);

Here again we define an anonymous class which extends from Label. We also override one of the methods in Label, getBackground(). when this frame is displayed, you will notice that the label has a yellow background.

All these are different from add(new Label("My Label")). With this statement, you are just using the class Label. No class are created (look at your file system).
Avatar of HanRui

ASKER


Ok. I didn't realize that new Label(String) {..} was creating a new class because I never thought about the {...}. Your explanation explains why I see new $ classes of the anonymous ActionListener(){...} stuff in my directory after I created anonymous ones.

Still, if you only have add(new Label("Hello")); I wonder if a new class is bring created or just an instance of Label. Maybe so. I haven't tested that to see the behavior of the compiler.

Thanks for being persistent until I understood it.
When you write add(new Label("Hello")), you are not defining a new class (no class file created). What you have done is to create an instance of Label in memory. The reference to this instance is passed to the add() method.

>Thanks for being persistent until I understood it.

Well too bad I don't get any points for that. :-)
Avatar of HanRui

ASKER


I agree about the points. Sorry. But at least you helped someone out, and I do appreciate it!