2014-12-19 175 views
7

我有一個局部變量訪問內部類的問題需要聲明爲final。它來自方法createGrids() - >「squares[i][j] = 0;」,我是一個局部變量,需要聲明爲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<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); 
    } 
} 
+0

[變量可能在內部類中被訪問。需要被宣佈爲最終](http://stackoverflow.com/questions/14425826/variable-is-accessed-with-inner-class-needs-to-be-declared-final) – Suragch 2016-12-05 05:00:51

回答

20

匿名內部類可以訪問本地變量通過幕後的把戲。局部變量被實現爲內部類的隱藏成員變量。他們被分配了局部變量的副本。爲了防止複製值錯誤,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但從來沒有改變過一次初始化。

+0

真正的問題是爲什麼他們使用複印件? – Ced 2016-06-04 18:29:48

4

正在發生的事情是,你正在創建81的ActionListener類,每一個都有自己的actionPerformed方法。但是當這個方法被執行時,班級不知道ij的值是什麼,因爲它讓他們遠遠落後。

Java防止發生這種情況,因此編譯器錯誤。它要求任何引用的局部變量都是最終的,以便它可以將它們傳遞給創建的類。

解決這個最簡單的方法是創建一個對final變量的循環裏:

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]); 
    } 
} 
相關問題