GameFrame
class contains a class named MyActionListener
.import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
class GameFrame extends JFrame {
private static final long serialVersionUID = 1L;
int randomNumber = new Random().nextInt(10) + 1;
int numGuesses = 0;
JTextField textField = new JTextField(5);
JButton button = new JButton("Guess");
JLabel label = new JLabel(numGuesses + " guesses");
public GameFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
add(textField);
add(button);
add(label);
button.addActionListener(<strong>new MyActionListener()</strong>);
pack();
setVisible(true);
}
<strong> </strong>
<strong>class MyActionListener implements ActionListener {</strong>
@Override
public void actionPerformed(ActionEvent e) {
String textFieldText = <strong>textField</strong>.getText();
if (Integer.parseInt(textFieldText) == randomNumber) {
button.setEnabled(false);
textField.setText(textField.getText() + " Yes!");
textField.setEnabled(false);
} else {
textField.setText("");
textField.requestFocus();
}
numGuesses++;
String guessWord = (numGuesses == 1) ? " guess" : " guesses";
label.setText(numGuesses + guessWord);
}
<strong>}</strong>
}
The MyActionListener
class above is an inner class. An inner class is a lot like any other class. But within an inner class’s code, you can refer to the enclosing class’s fields. For example, several statements inside MyActionListener
use the name textField
, and textField
is defined in the enclosing GameFrame
class.
Notice that the code above uses the MyActionListener
class only once. (The only use is in a call to button.addActionListener
.) So, do you really need a name for something that’s used only once? No, you don’t. You can substitute the entire definition of the inner class inside the call to button.addActionListener
. When you do this, you have an anonymous inner class. This is how it works.
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
class GameFrame extends JFrame {
private static final long serialVersionUID = 1L;
int randomNumber = new Random().nextInt(10) + 1;
int numGuesses = 0;
JTextField textField = new JTextField(5);
JButton button = new JButton("Guess");
JLabel label = new JLabel(numGuesses + " guesses");
public GameFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
add(textField);
add(button);
add(label);
button.addActionListener(<strong>new ActionListener() {</strong>
@Override
<strong>public void actionPerformed(ActionEvent e) {</strong>
String textFieldText = textField.getText();
if (Integer.parseInt(textFieldText) == randomNumber) {
button.setEnabled(false);
textField.setText(textField.getText() + " Yes!");
textField.setEnabled(false);
} else {
textField.setText("");
textField.requestFocus();
}
numGuesses++;
String guessWord = (numGuesses == 1) ? " guess" : " guesses";
label.setText(numGuesses + guessWord);
<strong>}</strong>
<strong>}</strong>);
pack();
setVisible(true);
}
}
Inner classes are good for things like event handlers, such as the actionPerformed
method. The most difficult thing about an anonymous inner class is keeping track of the parentheses, the curly braces, and the indentation Some humble advice: start by writing code without any inner classes. Later, when you become bored with ordinary Java classes, experiment by changing some of your ordinary classes into inner classes.