Java 为什么匿名方法和类字段中的变量必须是最终变量;T

Java 为什么匿名方法和类字段中的变量必须是最终变量;T,java,attributes,anonymous-methods,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

如果我有这个匿名方法,我应该声明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();
            }
          });
}
private void测试方法(ListField-ListField){
最终列表加载器=新的页面列表加载器();
addListener(Events.Attach,new Listener()){
@凌驾
公共无效handleEvent(ListViewEvent be){
loader.load();
}
});
}
但是,如果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;
        }
}
公共类testClass{
私有ListLoader=新的PagedListLoader();
私有void测试方法(ListField ListField){
addListener(Events.Attach,new Listener()){
@凌驾
公共无效handleEvent(ListViewEvent be){
loader.load();
}
});
//在方法执行之前,我可以在这里修改加载程序的引用吗?
//加载器=null;
}
}

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

看看java中的Lambdas和concures

匿名内部类周围没有任何信息——您必须指定它是final,这样才能保证它的存在

这可能与
ListLoader
的性质有关,但我对使用这个库没有经验


我希望我为您指出了正确的方向。

匿名类通过构造函数隐式获取局部变量。也就是说,他们得到了他们使用的本地变量的副本。因此,如果我们更改了主代码中的变量值,匿名类将不会看到这种更改。声明本地变量final有助于避免这种歧义

根据java

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

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


局部变量在堆栈中分配,在
testMethod()
之后,它将不在范围内。将变量设置为final可以确保将对它的引用传递给匿名类。如果它不是final,则稍后在
testMethod()
中对其赋值可能会更改该值,导致结果混乱。(用户可能希望稍后使用指定的值,但这是不可能的)


但是,可以通过匿名类的父引用访问父类的字段,因此以后的任何分配都可以处理而不会混淆。

@jlordo。不完全是。这篇文章没有讨论字段,只是讨论局部变量。同样的原则也适用。这是一个(匿名)内部类,它引用了外部类的封闭实例,因此可以访问它的字段。这里的另一个我想我没有正确解释它。我的问题是关于字段,而不是局部变量,这是我无法理解的。为什么他们想要保证局部变量不改变,并且不在类字段上这样做?想想如果局部变量超出范围会发生什么?例如,假设您提交了一些使用一些局部变量的未来任务,从现在起2小时后开始,并且当前方法已退出。当这些值从堆栈中消失时,您将如何返回到原始值?但是,如果字段的内容在此期间发生了更改怎么办?@AminAbu Taleb由于访问通过父引用,内部类始终可以使用最新的值。这就是我要寻找的。