访问内部类的局部变量需要声明为final [英] Local variable access to inner class needs to be declared final

查看:26
本文介绍了访问内部类的局部变量需要声明为final的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了对内部类的局部变量访问需要声明为final的问题.从方法 createGrids() -> "squares[i][j] = 0;" 可以看出 i 是需要声明为 final 的局部变量.我不知道为什么,我在字段中添加了 final,但效果不佳.

I got a problem of local variable access to inner class need to be declared final. It is from method createGrids() -> "squares[i][j] = 0;" that i is a local variable that need to be declared final. I don't know why and I have added final in fields but it is not working as well.

import java.util.ArrayList;
import java.util.Random;

//省略

public class Minesweeper{
    private JFrame frame;
    private int cols = 9;
    private int rows = 9;
    public static final int GRID_HEIGHT = 9;
    public static final int GRID_WIDTH = 9;
    final JButton[][] grids = new JButton[GRID_WIDTH][GRID_HEIGHT];
    final int [][] squares = new int [GRID_WIDTH][GRID_HEIGHT];
    private static int width = 500;
    private static int heigth = 400;

    private JPanel s;
    private JPanel n;
    private JPanel w;
    private int mines = 10;
    private int bomb = 1;
    private JLabel j1;
    private JPanel e;
    private JRadioButton moreGrid;
    ArrayList<Integer> list = new ArrayList<Integer>();

    public Minesweeper() {
        mines=10;
        createGrids();
        s = new JPanel();
        n = new JPanel();
        e = new JPanel();
        w = new JPanel();

        resetButton = new JButton("Rest");
        resetButton.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e){ createGrids();}
            });
        newGameButton = new JButton("New Game");
        frame.add(n, BorderLayout.NORTH);
        frame.add(w, BorderLayout.WEST);
        frame.add(s, BorderLayout.SOUTH);
        s.add(resetButton);
        s.add(newGameButton);
    }

    public void game()
    {
        for(int i = 0; i < GRID_WIDTH; i++) {
            for(int j = 0; j < GRID_HEIGHT; j++) {
                squares[i][j] = 0;
            }
        }
    }
    public void setRandom()
    {
        Random r = new Random();
        for(int x = 0; x < mines; x++){
            int b = r.nextInt(9);
            int c = r.nextInt(9) ;   
            squares[b][c] = bomb;   
        }
    }

    public void createGrids(){
        frame = new JFrame("Minesweeper");
        createMenuBar(frame);
        frame.setTitle("Nicholas Minesweeper");
        JPanel m = new JPanel(new GridLayout(9,9));
        for(int i = 0; i < GRID_WIDTH; i++) {
            for(int j = 0; j < GRID_HEIGHT; j++) {
                grids[i][j] = new JButton();
                grids[i][j].addActionListener(new ActionListener(){
                    public void actionPerformed(ActionEvent e){ 
                        if (squares[i][j] == 1)
                        {
                           System.out.println("BOmb");
                        }
                        else {
                            grids[i][j].setVisible(false);
                        }
                    }
                });
                m.add(grids[i][j]);
            }
        }
        frame.add(m, BorderLayout.CENTER);
        frame.setResizable(false);
        frame.setSize(width, heigth);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setSize(350, 250);
        frame.setVisible(true); 
    } 
}

推荐答案

匿名内部类可以通过幕后的技巧访问局部变量.局部变量被实现为内部类的隐藏成员变量.它们被分配了局部变量的副本.为了防止复制值出错,Java 编译器强制这些局部变量必须是 final 以便它们不会被更改,因此副本保持正确.

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.

封闭类的字段不需要是final;使用的局部变量必须是 final.您必须使匿名内部类中使用的所有局部变量final.你可以通过声明 final 变量来初始化你的 ij 值,并在你的匿名内部类中使用它们.>

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);
        }
    }
 });

请注意,在 Java 8 中,这不是必需的,因为 Java 8 编译器可以检测匿名内部类中使用的局部变量是否有效最终",即不是 final 而是初始化后永不改变.

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.

这篇关于访问内部类的局部变量需要声明为final的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆