2011-05-10 41 views
7

当地最后一个变量我有以下代码:问题有关使用Java

public class BookLib { 
    void f() { 
     final int x = 5; // Line 1 
     class MyCLass { 
      void print() { 
       System.out.println(x); 
      } 
     } 
    } 
} 

我不明白为什么要在这种情况下(1号线)使用最后一个变量?

+0

[关于Java中的本地最终变量](http://stackoverflow.com/questions/3013547/about-local-final-varibles-in-java) – 2011-05-10 08:36:56

+0

相关http://stackoverflow.com/questions/154314/ when-should-one-use-final – 2013-07-18 07:38:58

回答

19

你在这里创建了一个内部类。由于此类的对象的生命周期可能远远大于方法调用的运行时间(即对象在方法返回后仍可能存在很长时间),因此它需要“保留”它的局部变量的状态可以访问。

通过在内部类中创建一个(不可见的,合成的)副本并自动将所有对局部变量的引用替换为对该副本的引用来完成此保留。这个可能在局部变量在内部类对象创建后被修改时会导致奇怪的效果。

为了避免这种情况,需要以这种方式访问​​的所有本地变量都是final:这确保只有一个可能的局部变量值,并且没有观察到不一致。

这种特殊的规则可以在the JLS§8.1.3 Inner Classes and Enclosing Instances发现:

任何局部变量,形式化方法参数或使用异常处理程序参数,但在一个内部类没有声明必须声明为final。任何使用但未在内部类中声明的局部变量必须在内部类的主体之前明确指定(§16)

+2

我们在这里谈论什么奇怪的影响?最终的变量是不是存储在堆栈框架中? – rogerdpack 2011-10-17 18:45:51

3

这里创建一个内部类。为了访问执行上下文,对变量的引用应保持不变,否则会出现错误行为。为了保证这一点,你应该声明你的变量final:因此不能改变它。

查看详细解释here

0

所以你有一个本地最终变量和方法本地内部类。方法局部内部类不能使用在方法(包括参数)中声明的非最终变量。

深入研究: 方法局部内部类只能在定义类的方法中实例化。局部变量在方法的整个生命周期内都处于堆栈状态。当方法结束时,局部变量消失,但是创建的内部类对象仍然存在。

这是一生/范围的问题。

+0

它可以使用(非final)字段... – krookedking 2011-05-10 08:45:16

+0

@krookedking它不能使用方法(包括参数)中声明的非最终变量。 – Jurri 2011-05-10 08:47:48

+0

对不起,我解释为“不能使用除最终局部变量之外的任何东西”作为“不能使用除最终局部变量之外的任何东西” – krookedking 2011-05-10 08:55:31

1

从凯西塞拉利昂SCJP书

方法的局部变量存在于栈中,只有该方法的生命周期存在。我们已经知道局部变量的范围仅限于声明变量的方法。当方法结束时,堆栈帧被吹走并且变量是历史记录。但即使在方法完成之后,如果其中创建的内部类对象可能仍然存在于堆中,例如,对它的引用被传递到其他代码中,然后存储在实例变量中。因为只要方法局部的内部类对象不存在局部变量,内部类对象就不能使用它们。除非局部变量标记为最终!