为什么变量必须在匿名方法中是最终的,而类字段则不是

Ami*_*leb 5 java attributes anonymous-methods

如果我有这个匿名方法,我应该声明x变量为final.

private void testMethod (ListField<BeanModel> listField){

     final ListLoader<BeanModel> loader = new PagedListLoader<BeanModel>();
     listField.addListener(Events.Attach, new Listener<ListViewEvent<BeanModel>>() {

            @Override
            public void handleEvent(ListViewEvent<BeanModel> be) {
                loader.load();
            }
          });
}
Run Code Online (Sandbox Code Playgroud)

但是,如果loader是一个类字段,则没有必要将其声明为final:

public class testClass{

    private ListLoader<BeanModel> loader = new PagedListLoader<BeanModel>();

    private void testMethod (ListField<BeanModel> listField){
        listField.addListener(Events.Attach, new Listener<ListViewEvent<BeanModel>>() {

                    @Override
                    public void handleEvent(ListViewEvent<BeanModel> be) {
                        loader.load();
                    }
                  });

        //Could I modify loader's reference here, before the method executes?
        //loader = null;
        }
}
Run Code Online (Sandbox Code Playgroud)

有没有人知道为什么他们保证局部变量在被访问时不会改变但是没有为类字段做?

Pra*_*ker 9

正在编写java 文档

匿名类可以访问其封闭类的成员.
匿名类无法访问其封闭范围中未声明为final或者有效final的局部变量(有效最终意味着变量在初始化后永远不会更改.方法参数通常是最终的.)

如果我们对本地课程的实施方式有所了解,那么这种限制的原因就显而易见了.匿名本地类可以使用局部变量,因为编译器会自动为类提供一个私有实例字段来保存类使用的每个局部变量的副本.编译器还为每个构造函数添加隐藏参数,以初始化这些自动创建的私有字段.因此,本地类实际上并不访问本地变量,而只是它们自己的私有副本.这种方法可以正常工作的唯一方法是将局部变量声明为final,以确保它们不会改变.有了这种保证,本地类就可以确保其变量的内部副本能够准确地反映实际的局部变量.

  • 想想如果局部变量超出范围会发生什么?例如,假设您使用一些局部变量提交了一些未来任务,以便在 2 小时后启动,并且当前方法已退出。当这些原始值从堆栈中消失时,您将如何恢复它们? (2认同)

kih*_*eru 5

局部变量在栈中分配,之后就会脱离作用域testMethod()。将变量设置为final 确保可以将对其的引用传递给匿名类。如果它不是最终的,稍后对其进行赋值testMethod()可能会更改该值,从而导致令人困惑的结果。(用户可能期望使用稍后分配的值,但这是不可能的)。

但是,可以通过匿名类的父引用访问父类的字段,因此可以毫无混乱地处理任何后续分配。