对内部类的本地变量访问需要声明为final

 东营市第一中学李芳 发布于 2022-12-04 15:25

我遇到了一个局部变量访问内部类的问题需要被声明为final.它来自方法createGrids() - >" squares[i][j] = 0;",我是一个需要声明为final的局部变量.我不知道为什么和我在字段中添加了final,但它不能正常工作.

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 list = new ArrayList();

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

rgettman.. 23

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

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

// 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初始化后不会更改.

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

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

    // 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初始化后不会更改.

    2022-12-11 03:11 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有