【问题标题】:Where are Java final local variables stored?Java最终局部变量存储在哪里?
【发布时间】:2009-12-22 11:02:00
【问题描述】:

举个例子:

public void init() {
    final Environment env = new Environment();
    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
             env.close();
        }
     });
}

首先,env 存储在哪里?是吗:

  • 由编译器复制到引用它的内部类的隐藏成员变量中
  • 复制到堆并在堆上引用
  • 留在堆栈上并以某种方式在那里引用
  • 别的东西

我的猜测是第一个选项。

其次,解决由此产生的任何性能问题(而不是简单地将env 创建为类的成员变量并引用它),特别是如果您正在创建大量引用 final 的此类内部类构造局部变量。

【问题讨论】:

    标签: java performance final local-variables


    【解决方案1】:

    是的,它们是被复制的,这就是你必须将变量声明为 final 的原因。这样一来,它们就可以保证在复制完成后不会更改。

    这与实例字段不同,即使不是最终字段也可以访问。在这种情况下,内部类获得对其用于此目的的外部实例的引用。

    private Environment env;  // a field does not have to be final
    
    public void init() {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                 env.close();
            }
         });
    }
    

    其次,这样做会产生任何性能问题吗?

    与什么相比?您需要有字段或变量才能让您的内部类工作,而副本是一种非常有效的方法。无论如何,它只是一个“浅”副本:只是复制了对(在您的示例中)环境的引用,而不是环境本身。

    【讨论】:

    • 那么我可以假设这样做不会导致性能问题吗?
    • 我个人在这方面的不满是对外部实例的引用(用于访问被复制的字段,而不是变量)可能是一个问题,如果它们不需要的话:stackoverflow.com/questions/758570/…
    • 与将其作为成员变量引用相比。如果它被复制,那么我的假设是不会影响性能。
    • 是的,它是一样的(只是更少的输入),因为您实际上是在幕后引用编译器在内部类中为您创建的合成成员变量来保存最终变量。
    • 如果您添加让您相信这一点的参考资料或作品,您将获得我的支持。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 2021-10-18
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多