Java 为什么将ActionListener添加到JButton时,这两个类似的for循环会有不同的结果?

Java 为什么将ActionListener添加到JButton时,这两个类似的for循环会有不同的结果?,java,for-loop,jbutton,Java,For Loop,Jbutton,最初我有一个JFrame,它有3个按钮:哪个按钮0单击时打印0,按钮1打印1,依此类推: JFrame jframe=new JFrame(); jframe.getContentPane().setLayout(new GridLayout(3,1)); for(int i=0;i<3;i++){ final int j=i; JButton jbutton=new JButton(""+j); jframe.getContentPane().add(jbutto

最初我有一个JFrame,它有3个按钮:哪个按钮0单击时打印0,按钮1打印1,依此类推:

JFrame jframe=new JFrame();
jframe.getContentPane().setLayout(new GridLayout(3,1));
for(int i=0;i<3;i++){
    final int j=i;
    JButton jbutton=new JButton(""+j);
    jframe.getContentPane().add(jbutton);
    jbutton.setPreferredSize(new Dimension(100,100));
    jbutton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            System.out.println(""+j);
        }
    });
}
jframe.setVisible(true);
jframe.pack();
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
由于最后一个变量,我想减少1行,因此重构for循环如下:

JFrame jframe=new JFrame();
jframe.getContentPane().setLayout(new GridLayout(3,1));
for(final int[] arr={0};arr[0]<3;arr[0]++){
    JButton jbutton=new JButton(""+arr[0]);
    jframe.getContentPane().add(jbutton);
    jbutton.setPreferredSize(new Dimension(100,100));
    jbutton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            System.out.println(""+arr[0]);
        }
    });
}
jframe.setVisible(true);
jframe.pack();
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

但是这次所有按钮都打印3,即使按钮索引仍然是0,1,2,原因是什么?

在第二个程序中,您将相同的变量传递给所有三个按钮。然后在每次迭代中增加变量的值。因此,所有三个按钮的值都会更新

我举个简单的例子

class Resource{
    int a = 10;
}
class A{
    Resource r;
}
class B{
    public static void main(String args[]){
        Resource r = new Resource();

        A o1 = new A();
        o1.r = r;

        A o2 = new A();
        o2.r = r;

        o1.r.a = 20;

        System.out.println(o1.r.a);  // prints 20
        System.out.println(o2.r.a);  // prints 20 too
    }
}
循环结束后,i[0]为3。ActionListener都持有对i的引用,并将读取i[0]的相同值,即3

如果要更正此问题,请将i[0]的值指定给一个局部最终变量,并将其指定给输出,如:

for(int[] arr = {0}; arr[0] < 3; arr[0]++) {
    final int val = arr[0];
    ...
    jbutton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            System.out.println("" + val);
        }
    });
}

正确的方法是获取事件源,然后不需要final int

为什么要对final int[]arr={0}使用数组;arr[0]arr[0]+。。。循环完成时,arr[0]处的值是多少?
for(int[] arr = {0}; arr[0] < 3; arr[0]++) {
    final int val = arr[0];
    ...
    jbutton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            System.out.println("" + val);
        }
    });
}
    public static void main(String [] args)
    {
        JFrame jframe=new JFrame();
        jframe.getContentPane().setLayout(new GridLayout(3,1));
        for(int i=0;i<3;i++){
            JButton jbutton=new JButton(""+ i);
            jframe.getContentPane().add(jbutton);
            jbutton.setPreferredSize(new Dimension(100,100));
            jbutton.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e){
                    JButton myButton = (JButton)e.getSource();
                    System.out.println(""+ myButton.getText());
                }
            });
        }
        jframe.setVisible(true);
        jframe.pack();
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    
    }