为什么在匿名类中只能访问最终变量? [英] Why are only final variables accessible in anonymous class?

查看:27
本文介绍了为什么在匿名类中只能访问最终变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  1. a 在这里只能是最终的.为什么?如何在 onClick() 方法中重新分配 a 而不将其保留为私有成员?

  1. a can only be final here. Why? How can I reassign a in onClick() method without keeping it as private member?

private void f(Button b, final int a){
    b.addClickHandler(new ClickHandler() {

        @Override
        public void onClick(ClickEvent event) {
            int b = a*5;

        }
    });
}

  • 如何在点击时返回 5 * a ?我的意思是,

    private void f(Button b, final int a){
        b.addClickHandler(new ClickHandler() {
    
            @Override
            public void onClick(ClickEvent event) {
                 int b = a*5;
                 return b; // but return type is void 
            }
        });
    }
    

  • 推荐答案

    如评论中所述,其中一些在 Java 8 中变得无关紧要,其中 final 可以是隐式的.但是,在匿名内部类或 lambda 表达式中只能使用 有效 final 变量.

    As noted in comments, some of this becomes irrelevant in Java 8, where final can be implicit. Only an effectively final variable can be used in an anonymous inner class or lambda expression though.

    这主要是由于 Java 管理闭包的方式.

    It's basically due to the way Java manages closures.

    当您创建匿名内部类的实例时,该类中使用的任何变量都会通过自动生成的构造函数复制其.这避免了编译器必须自动生成各种额外类型来保存局部变量"的逻辑状态,例如 C# 编译器所做的......(当 C# 捕获匿名函数中的变量时,它确实捕获了变量 -闭包可以以方法主体看到的方式更新变量,反之亦然.)

    When you create an instance of an anonymous inner class, any variables which are used within that class have their values copied in via the autogenerated constructor. This avoids the compiler having to autogenerate various extra types to hold the logical state of the "local variables", as for example the C# compiler does... (When C# captures a variable in an anonymous function, it really captures the variable - the closure can update the variable in a way which is seen by the main body of the method, and vice versa.)

    由于该值已被复制到匿名内部类的实例中,所以如果该变量可以被方法的其余部分修改,那将看起来很奇怪 - 您可能有似乎正在使用的代码 -日期变量(因为这实际上是将要发生的...您将使用在不同时间拍摄的副本).同样,如果您可以在匿名内部类中进行更改,开发人员可能希望这些更改在封闭方法的主体中可见.

    As the value has been copied into the instance of the anonymous inner class, it would look odd if the variable could be modified by the rest of the method - you could have code which appeared to be working with an out-of-date variable (because that's effectively what would be happening... you'd be working with a copy taken at a different time). Likewise if you could make changes within the anonymous inner class, developers might expect those changes to be visible within the body of the enclosing method.

    将变量设为 final 消除了所有这些可能性——因为该值根本无法更改,因此您无需担心此类更改是否可见.允许方法和匿名内部类看到彼此更改的唯一方法是使用某种描述的可变类型.这可能是封闭类本身,一个数组,一个可变的包装类型......任何类似的东西.基本上它有点像在一个方法和另一个方法之间进行通信:对一个方法的参数所做的更改不会被其调用者看到,但是对引用的对象所做的更改由参数可见.

    Making the variable final removes all these possibilities - as the value can't be changed at all, you don't need to worry about whether such changes will be visible. The only ways to allow the method and the anonymous inner class see each other's changes is to use a mutable type of some description. This could be the enclosing class itself, an array, a mutable wrapper type... anything like that. Basically it's a bit like communicating between one method and another: changes made to the parameters of one method aren't seen by its caller, but changes made to the objects referred to by the parameters are seen.

    如果您对 Java 和 C# 闭包之间更详细的比较感兴趣,我有一篇文章 更进一步.我想在这个答案中关注 Java 方面:)

    If you're interested in a more detailed comparison between Java and C# closures, I have an article which goes into it further. I wanted to focus on the Java side in this answer :)

    这篇关于为什么在匿名类中只能访问最终变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆