草庐IT

java - 访问内部类的局部变量需要声明为final

coder 2024-03-14 原文

我遇到了一个问题,即访问内部类的局部变量需要声明为 final。从方法 createGrids() -> "squares[i][j] = 0;"可以看出,i 是一个需要声明为 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<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,这样它们就不会被更改,因此复制保持正确。

封闭类的字段不需要是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 但一旦初始化就永远不会改变。

关于java - 访问内部类的局部变量需要声明为final,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27558425/

有关java - 访问内部类的局部变量需要声明为final的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  3. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  4. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  5. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  6. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  7. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  8. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

随机推荐