加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java中的内部块如何访问应该超出范围的局部变量? (JVM如何处理J

发布时间:2020-12-15 08:43:44 所属栏目:Java 来源:网络整理
导读:在以下代码中: public class Main{ Emp globalEmp; public void aMethod() { final int stackVar = 10; globalEmp = new Emp() { public void doSomeThing() { System.out.println("stackVar :" + stackVar); } }; } public static void main(String[] args
在以下代码中:

public class Main
{
    Emp globalEmp;

    public void aMethod()
    {
        final int stackVar = 10;

        globalEmp = new Emp()
        {
            public void doSomeThing()
            {
                System.out.println("stackVar :" + stackVar);
            }
        };
    }

    public static void main(String[] args)
    {
        Main m = new Main();
        m.aMethod();
        m.globalEmp.doSomeThing();
    }
}

interface Emp{
    public void doSomeThing();
}

据我所知,将执行以下操作:

> Main m = new Main(); :将创建一个新的Main类实例,并将globalEmp设置为null.
> m.aMethod(); :调用aMethod,包括将其实例变量stackVar复制到堆栈中,然后创建Emp类的新实例并将其分配给globalEmp实例.
>当方法aMethod到达结束时,局部变量stackVar将从堆栈中推出.
> m.globalEmp.doSomeThing(); :将在globalEmp变量指向的先前创建的对象上调用函数doSomeThing.并且因为这个函数doSomeThing正在访问一个本地变量stackVar,它假定不会从缓存中弹出,它应该抛出一些错误说明.

那么,Java运行时如何真正起作用呢?

编辑:

>由于运行时将创建最终局部变量的浅表副本(下面的每个答案),为什么它也不允许访问非最终变量?
>你能否提供一些链接(在规格或官方地方)?

解决方法

通常,匿名内部类将为其生成一个构造函数,以获取在匿名内部类的类中引用的局部变量的值.生成的代码转为:

globalEmp = new Emp() { ... };

成:

globalEmp = new Main$1(stackVar);

然后,该构造函数将值复制到生成的匿名类中的隐藏字段中.

换句话说,它会创建值的副本.之后,原始值来自的变量无关紧要.

在您实际显示的情况下,它不需要因为10是常量 – 但这是捕获变量的一般方式.

编辑:回应你的编辑…

变量必须是最终的,这样就不会出现混淆 – 如果你可以改变它们,一些开发人员可能希望在匿名类中可以看到任何变化,就像在其他闭包实现中一样.

至于围绕这个的官方文档,我在Java语言规范中看到的最接近的是section 8.1.3,尽管它没有讨论各种决策背后的动机.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读