addActionListener中如何使用外部变量?

for (int i = 0; i < 10; i++) {
BTN[i] = new JButton("" + i);
BTN[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textField.setText(""+i); //这里会出错的
}
});

}

addActionListener中如何使用变量i?请直接贴代码...有代码+解释更好.3q
final int i;不行啊...还是会出错的..访问有问题.

final是可以的……只是不知道你有没有写对而已:
[code="java"]import java.awt.event.*;
import javax.swing.*;

public class Demo {
private static void populateGUI() {
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel panel = new JPanel();
frame.add(panel);

final JTextField field = new JTextField(5);
panel.add(field);

for (int i = 1; i <= 3; i++) {
  final int j = i;
  JButton button = new JButton(Integer.toString(i));
  button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
      field.setText(Integer.toString(j));
    }
  });
  panel.add(button);
}

frame.pack();
frame.setVisible(true);

}

public static void main(String[] args) {

SwingUtilities.invokeLater(new Runnable() {
public void run() {
populateGUI();
}
});
}
}[/code]
在这个ActionListener里用了两个局部变量,field和j,两个都必须声明为final。
声明为final之后变量就不可修改了,如果要在匿名内部类里修改外部变量的值的话,还是把要改的值写为成员变量吧……或者重新评估一下是否真的需要在内部类里去修改外部变量。

你把 用到外部变量的那段代码 用一个方法抽取到外部

例如JButton button = new JButton("");
int i = 8;
public void test(){
button.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {
get();
}
});
}

void get(){
i = 10;
}
最好别用声明final那种方法 以后不好维护 代码多了 看着乱

LZ有两个错误

(1) 匿名内部类使用外部类的变量一定要用final修饰,所以i必须用final修饰

(2) 如果i用final修饰也会报错,因为一旦i成为常量,是不允许第二次修改i里面的值的。所以for循环中的i++是不可能实现的。

1楼的代码解决的很好:
[code="java"]
for (int i = 1; i <= 3; i++) {

final int j = i;

JButton button = new JButton(Integer.toString(i));

button.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

field.setText(Integer.toString(j));

}

});

panel.add(button);

}

[/code]

在这里 for循环3次分别创建了3个常量j,而不是把常量j赋值了3次。这就解决了常量j不允许修改的问题。

解释一下匿名内部类和局部内部类调用外部变量一定要是final的原因。
假设有这么一段代码:
class Outter{
public void runOut{
int i=0;
class Inner{
public void runIn{
//使用i
}
}
Inner inner=new Inner();
inner.runIn();
}
}
当JVM运行到inner.runIn()语句之后,这是线程开始运行Inner类中的内容,而Outter类全部运行完毕。JVM的垃圾回收机制很有可能及时释放掉局部变量i的内存。试问,如果i被释放了,内部类Inner怎么才能使用上i呢。
其实,编译器起了很大的作用,编译器已经在Inner类中备份了一个i变量。我们可以通过反射Inner类看到这条新加的语句: final int val$i;
也就是说即使外部类的i没有了,内部类也有一个备份可供使用。
但问题也来了,如果外部类的i变量会不停的变化,内部类备份的i是不是要不停的跟着变那,这对线程同步来说是个很大的麻烦,所以干脆就将外部类的i强制设置成final常量,这样就不会有任何问题了。