2009-12-22 48 views
18

看看下面的例子:Java最终局部变量存储在哪里?

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

首先,在那里被存储env?是:

  • 由编译器复制到内部类的隐藏成员变量引用它
  • 复制到,并参考上,堆
  • 留在堆栈上并以某种方式引用的有
  • 别的

猜测是第一个选项。

其次,做这样做会产生任何性能问题(而不是简单地创建env作为类的成员变量并引用它),特别是如果您要创建大量引用最终本地的此类内部类结构变量。

回答

18

是的,它们被复制,这就是为什么你必须声明变量为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(); 
     } 
    }); 
} 

其次,这样做从这样产生的任何性能问题?

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

+0

那么我可以假设这样做没有性能问题? – Joel 2009-12-22 11:08:42

+0

我的私人宠物在这方面是,对外部实例(用于访问字段,而不是变量,被复制)的引用可能是一个问题,如果他们不需要:http://stackoverflow.com/questions/ 758570/is-it-it-possible-make-anonymous-inner-classes-in-java-static – Thilo 2009-12-22 11:15:30

+0

相比于将它引用为成员变量。如果它被复制,那么,我的假设是没有性能影响。 – Joel 2009-12-22 11:17:00