Local variable access to inner class needs to be declared final

╄→尐↘猪︶ㄣ 提交于 2019-11-27 08:58:13

Anonymous inner classes have access to local variables through a trick behind the scenes. Local variable are implemented as hidden member variables of the inner class. They are assigned copies of the local variable. To prevent the copy value from being wrong, the Java compiler enforces that these local variables must be final so they aren't changed, so the copy stays correct.

The fields of the enclosing class don't need to be final; the local variables used must be final. You must make all local variables used in your anonymous inner class final. You can do this by declaring final variables to be initialized to your i and j values, and use them in your anonymous inner class.

// Inside the for loops in the createGrids method
grids[i][j] = new JButton();
// Declare x, y final
final int x = i;
final int y = j;
grids[i][j].addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e){ 
        // Use x, y instead of i, j inside.
        if (squares[x][y] == 1)
        {
             System.out.println("BOmb");
        }
        else {
             grids[x][y].setVisible(false);
        }
    }
 });

Note that in Java 8, this would not be necessary, because the Java 8 compiler can detect if the local variables used in anonymous inner classes are "effectively final", that is, not final but never changed once initialized.

What is happening is that you are creating 81 ActionListener classes, each one with its own actionPerformed method. But when that method is executed, the class doesn't know what the value of i and j is anymore, since it left them far behind.

Java prevents this from happening, hence the compiler error. It requires any referenced local variables to be final so that it can pass them to the created classes.

The simplest way to solve this is to create a pair of final variables inside your loops:

for(int i = 0; i < GRID_WIDTH; i++) {
    for(int j = 0; j < GRID_HEIGHT; j++) {
        grids[i][j] = new JButton();

        final int x = i; // <-- Add these
        final int y = j;

        grids[i][j].addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){ 
                if (squares[x][y] == 1) // <-- change from squares[i][j]
                {
                   System.out.println("BOmb");
                }
                else {
                    grids[x][y].setVisible(false); // <-- change from grids[i][j]
                }
            }
        });
        m.add(grids[i][j]);
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!