当前位置: 首页 > 面试题库 >

为什么在匿名类中只能访问最终变量?

丁雅逸
2023-03-14
问题内容
  1. a在这里只能是最终的。为什么?如何aonClick()不保留为私有成员的情况下重新分配方法?
private void f(Button b, final int a){
    b.addClickHandler(new ClickHandler() {

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

        }
    });
}
  1. 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中变得无关紧要,在Java 8中final可以隐式使用。但是,只能在匿名内部类或lambda表达式中使用有效的最终变量。

这基本上是由于Java管理闭包的方式。

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

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

将变量设为final消除了所有这些可能性-由于根本无法更改该值,因此您无需担心此类更改是否可见。允许方法和匿名内部类相互查看更改的唯一方法是使用某种描述的可变类型。这可能是封闭的类本身,一个数组,一个可变的包装器类型……诸如此类。基本上,这有点像一种方法与另一种方法之间的通信:调用者看不到对一个方法的参数所做的更改,但是可以看到对参数所引用的对象所做的更改。

如果您想对Java和C#闭包之间的更详细的比较感兴趣,请参阅我的文章。我想在这个答案中专注于Java方面:)



 类似资料:
  • 问题内容: 在这里只能是最终的。为什么?如何在不保留为私有成员的情况下重新分配方法? 单击该如何返回? 问题答案: 如注释中所述,其中一些在Java 8中变得无关紧要,在Java 8中final可以隐式使用。但是,只能在匿名内部类或lambda表达式中使用有效的最终变量。 这基本上是由于Java管理闭包的方式。 创建匿名内部类的实例时,该类中使用的任何变量都将通过自动生成的构造函数复制其值。这样避

  • 问题内容: 我正在阅读Java中的匿名类,它说您可以访问封闭类的方法,但不能访问局部变量。为什么会这样呢?我在说这个: 编辑:较旧的示例是不正确的,不能反映我的意思。根据在“访问封闭类的成员”一节中所写的内容,这应该是一个更好的示例,网址为http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html。 那么这个限制解决了什

  • 问题内容: 我了解为什么编译器不接受以下内容: 让我感到困惑的是,编译器接受以下内容,并且单元测试通过了: 为什么上述方法有效并且可以正常工作?欢迎使用指向JLS相关部分的指针(15.27.2节仅讨论局部变量)。 问题答案: 我们都同意第一个例子不能用,因为局部变量或参数必须是最终的或有效的最终才能在lambda表达式主体中使用。 但是您的第二个示例不涉及局部变量或参数,而是实例字段。Lambda

  • 问题内容: 在通过构造函数传递给匿名类的最终变量中,Jon Skeet提到了变量是通过自动生成的构造函数传递给匿名类实例的。在这种情况下,为什么我看不到使用反射的构造函数: } 输出为: 问题答案: 这是您的程序在我的系统上输出的内容: 因此,构造函数在那里。但是,它是无参数的。从反汇编来看,发生的事情是编译器发现它不需要传递给它,因为它的值在编译时就知道了。 如果我这样更改代码: 现在生成的构造

  • 在此代码示例中,ActionListener的actionPerformed函数中没有使用最终对象jLabel:

  • 问题内容: 这段代码: 印刷品: 我就是价值 但是,此代码: 导致编译错误: 为什么在我使用final类而不是隐式final枚举的同时,创建对我来说似乎是匿名子类的类,覆盖该方法,却抛出了编译时错误? 更具体地说,为什么可以覆盖中的任何内容?我对代码有印象 大致相当于 在这种情况下,匿名性质是不允许的。 有什么不同?为什么枚举很特别? 问题答案: 根据JLS: 枚举类型是隐式最终的,除非它包含至少