import java.awt.*; import java.applet.*; import java.awt.event.*; public class Bug extends Applet { Button b = new Button (); public void init() { class MyActionListener implements ActionListener { public MyActionListener() { } // constructor public void actionPerformed (ActionEvent e) { } } b.addActionListener(new MyActionListener()); // legal { b.addActionListener(new MyActionListener()); } // illegal } } javac Bug.java Bug.java:16: Class MyActionListener not found in type declaration. { b.addActionListener(new MyActionListener()); } // illegal ^ 1 error |
The for loop introduces a new scope (you can say for (int i; ...)). Braces, { }, also introduce a new scope. Within the new scope you should be able to access anything that you can outside the scope; but in fact, you cannot access the inner class MyActionListener.
This problem arises because the inner classes are declared within a method. The compiler allows you to do this, but that doesn't guarantee it is legal. (I have observed other illegal things that the compiler accepts.) Since there is no publicly available syntax of Java, I cannot tell whether it is illegal and the compiler just doesn't notice it, or whether it is legal and the compiler cannot handle the scoping.
Either way, it turns out that there is a simple workaround: Just move the inner class definitions out of the method, like this:
import java.awt.*; import java.applet.*; import java.awt.event.*; public class NoBug extends Applet { Button b = new Button (); class MyActionListener implements ActionListener { public MyActionListener() { } // constructor public void actionPerformed (ActionEvent e) { } } public void init() { b.addActionListener(new MyActionListener()); // legal { b.addActionListener(new MyActionListener()); } // illegal } } |
Notice that MyActionListener is still an inner class; it just isn't defined inside a method any more. It is still defined within the outer class NoBug.
By the way, anonymous inner classes can (and usually are) defined inside a method. But you can't refer to an anonymous class anyway, so scoping is not an issue.
Thanks to Bob Pollack for helping me with this.