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

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

问题描述

我遇到了一个局部变量访问内部类的问题需要被声明为final。它来自方法createGrids() - > squares [i] [j] = 0; 我是一个需要被声明为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 变量来初始化为 i j 值,并在匿名内部类中使用它们。

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天全站免登陆