Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Anonymous Inner Classes

Starting out with Java

Anonymous Inner Classes

by  scrat  Posted    (Edited  )
An inner class is where you define one class within another. You might do this where one class is tightly coupled to another class and there is no point in defining a new class.

// Outer.java
public class Outer {
Outer() {
Inner i = new Inner();
i.innerMethod();
}

// Inner class
private class Inner {
Inner() {}

public void innerMethod() {
// Do something.
}
}
}

Anonymous inner classes are classes that are created in situ within a method and can only be used once, where they are defined.

One classic use for an anonymous inner class is to implement the WindowListener interface in a Window. This lets a Window react to a number of standard window events, including reacting to the close button. The Window Listener interface dictates that an implementing class must define a number of methods. The Window class has a method addWindowListener(WindowListener) that allows the Window to receive window events.

So, you have a class that extends Frame (which is a subclass of Window):

// MyFrame.java
import java.awt.*;
public class MyFrame extends Frame {
MyFrame() {
super("MyFrame");
}
}

If you want to now add a WindowListener to the above, you have to first define a class that implements WindowListener, instantiate it and add it:

// MyWindowListener.java
import java.awt.event.*;
public class MyWindowListener implements WindowListener {
public void windowOpened(WindowEvent e) {}
public void windowClosing(WindowEvent e) {System.exit(0);}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}

// MyFrame.java
import java.awt.*;
public class MyFrame extends Frame {
MyFrame() {
super("MyFrame");
MyWindowListener myWindowListener = new MyWindowListener();
addWindowListener(myWindowListener);
}
}

Okay, the above will work but MyWindowListener is a bit trivial. It would be nice if it were associated with MyFrame. And it can be, as an inner class:

// MyFrame.java
import java.awt.*;
import java.awt.event.*;
public class MyFrame extends Frame {
MyFrame() {
super("MyFrame");
addWindowListener(new MyWindowListener());
}

private class MyWindowListener implements WindowListener {
public void windowOpened(WindowEvent e) {}
public void windowClosing(WindowEvent e) {System.exit(0);}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}
}

Much better. Now the WindowListener is not out on its own but inside the only class that is likely to use it.

But we can go one further with an anonymous inner class. Instead of going to the bother of creating MyWindowListener, we can define and add the WindowListener in one go:

// MyFrame.java
import java.awt.*;
import java.awt.event.*;
public class MyFrame extends Frame {
MyFrame() {
super("MyFrame");
WindowListener w = new WindowListener() {
public void windowOpened(WindowEvent e) {}
public void windowClosing(WindowEvent e) {System.exit(0);}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
};
addWindowListener(w);
}
}

Here, WindowListener w is created with the default constructor WindowListener(). Usually this would fail because WindowListener is an interface (not a class) and it does not support the required methods. But the interface methods are immediately implemented in a block within the braces following the constructor, so Java is happy. Usually you miss out the intermediate step of creating w and do this:

// MyFrame.java
import java.awt.*;
import java.awt.event.*;
public class MyFrame extends Frame {
MyFrame() {
super("MyFrame");
addWindowListener(new WindowListener() {
public void windowOpened(WindowEvent e) {}
public void windowClosing(WindowEvent e) {System.ext(0);}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
});
}
}

Anonymous inner classes can appear a bit confusing to start with and are sometimes difficult to notice in other programmerÆs code. The "});" is usually a telltale. They can cut down on trivial classes that you only need the once though, especially if you use an adapter class:

// MyFrame.java
import java.awt.*;
import java.awt.event.*;
public class MyFrame extends Frame {
MyFrame() {
super("MyFrame");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.ext(0);}
});
}
}

WindowAdapter implements all the methods required by the WindowListener interface. These methods do absolutely nothing, so you have to override the methods that you need, but you do not have to worry about the ones in which you are not interested.

When you compile a class with an anonymous inner class you get two compiled class files: in the above you get Frame.class and MyFrame$1.class.

If the class you are using as the base (e.g. WindowAdapter) has constructors that take arguments, there is nothing to stop you using these, but you cannot define new constructors for anonymous inner classes (because you do not get a chance to use them).

Usually the hardest bit about writing anonymous inner classes is getting the braces and parentheses and so forth to match up, so it is advisable to get things to compile at an early stage before tackling the method details. As a rule inner classes are small, convenience classes; if you find that you are having to write lots of detail in an inner class, it is probably time to separate it out into its own file.

-----------

P.S. To make any of the above runnable, add a main method to MyFrame:

public static void main(String[] args) {
MyFrame mf = new MyFrame();
mf.show();
}

Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top