我遇到了一个局部变量访问内部类的问题需要被声明为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; ArrayListlist = 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
变量声明为初始化为您的值i
和j
值来实现,并在匿名内部类中使用它们.
// 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
初始化后不会更改.
匿名内部类可以通过幕后技巧访问局部变量.局部变量实现为内部类的隐藏成员变量.它们被分配了局部变量的副本.为防止复制值出错,Java编译器强制要求这些局部变量必须final
不会更改,因此副本保持正确.
封闭类的字段不需要final
; 使用的局部变量必须是final
.您必须在匿名内部类中使用所有局部变量final
.您可以通过将final
变量声明为初始化为您的值i
和j
值来实现,并在匿名内部类中使用它们.
// 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
初始化后不会更改.