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

时间秒杀一切 提交于 2020-03-03 21:14:38
  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; } }); }
  2. 单击后如何返回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 } }); }

#1楼

也许这个把戏给你一个主意

Boolean var= new anonymousClass(){
    private String myVar; //String for example
    @Overriden public Boolean method(int i){
          //use myVar and i
    }
    public String setVar(String var){myVar=var; return this;} //Returns self instane
}.setVar("Hello").method(3);

#2楼

之所以只将访问限制在局部最终变量上,是因为如果所有局部变量都可以访问,则首先需要将它们复制到一个单独的部分,内部类可以访问这些部分并维护它们的多个副本。可变的局部变量可能会导致数据不一致。 最终变量是不可变的,因此复制到它们的任何数量都不会对数据的一致性产生任何影响。


#3楼

当在方法主体中定义匿名内部类时,可以从内部类中访问在该方法范围内声明为final的所有变量。 对于标量值,一旦将其赋值,最终变量的值就无法更改。 对于对象值,引用不能更改。 这允许Java编译器在运行时“捕获”变量的值,并将副本存储为内部类中的字段。 一旦外部方法终止并删除了其堆栈框架,原始变量就消失了,但是内部类的私有副本仍保留在该类自己的内存中。

http://en.wikipedia.org/wiki/Final_%28Java%29


#4楼

由于Jon拥有实现细节的答案,另一个可能的答案是JVM不想处理已结束激活的记录中的写操作。

考虑一下用例,您的lambda而不是被应用,而是存储在某个地方并稍后运行。

我记得在进行此类修改时,您会在Smalltalk中筹集非法商店。


#5楼

有一个技巧可以允许匿名类更新外部作用域中的数据。

private void f(Button b, final int a) {
    final int[] res = new int[1];
    b.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
            res[0] = a * 5;
        }
    });

    // But at this point handler is most likely not executed yet!
    // How should we now res[0] is ready?
}

但是,由于同步问题,此技巧不是很好。 如果稍后调用处理程序,则需要1)如果从不同线程调用了处理程序,则同步对res的访问2)需要具有某种标志或指示,表明res已更新

但是,如果立即在同一线程中调用匿名类,则此技巧行得通。 喜欢:

// ...

final int[] res = new int[1];
Runnable r = new Runnable() { public void run() { res[0] = 123; } };
r.run();
System.out.println(res[0]);

// ...
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!