匿名内部类中的 Java 局部变量可见性 - 为什么需要 'final' 关键字?

标签 java scope

我不明白为什么我不能总是从“监听器”或“处理程序”中访问变量。

这是我的代码:

Button btnDownload = new Button(myparent, SWT.NONE);
btnDownload.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                btnDownload.setEnabled(false); // I CAN'T 
            }
        });

唯一的方法是使用 final 关键字声明它:

final Button btnDownload = new Button(myparent, SWT.NONE);

为什么我需要声明一个变量 final 才能在事件中获得访问权限?

最佳答案

您的 SelectionAdapter 是一个匿名内部类,我认为这很清楚:

本地类绝对可以引用实例变量。它们不能引用非 final 局部变量的原因是因为局部类实例在方法返回后可以保留在内存中。当方法返回时,局部变量超出范围,因此需要它们的副本。如果变量不是最终的,那么方法中的变量副本可能会改变,而本地类中的副本不会改变,所以它们会不同步。

匿名内部类需要 final 变量,因为它们是在 Java 中实现的。匿名内部类 (AIC) 通过创建一个私有(private)实例字段来使用局部变量,该字段保存局部变量值的副本。内部类实际上并没有使用局部变量,而是一个副本。在这一点上应该很明显,如果原始值或复制值发生变化,就会发生“坏事”™;会有一些意想不到的数据同步问题。为了防止此类问题,Java 要求您将 AIC 将使用的局部变量标记为最终变量(即不可更改)。这保证了内部类的局部变量副本将始终与实际值匹配。

关于匿名内部类中的 Java 局部变量可见性 - 为什么需要 'final' 关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7423028/

相关文章:

java - 试图调用本地数据库变量并且应用程序停止工作

java - 如何获取声明的对象类型的字段?

java - Spring Boot Maven pom.xml 不存在

java - 如何打印与变量值对应的一组字符?

javascript - 谁能解释这种意外的 V8 JavaScript 性能行为?

java - 如何访问大括号内的整数?

c# - Unity3D C# - 变量范围

java - hibernate : Objects are getting saved without transaction Object

ruby-on-rails-3 - Rails 3 路由范围和/或嵌套

c++ - 是否可以在 C++ 中增加变量范围?