Java范围和生命周期(内部类)

时间:2012-02-05 21:06:17

标签: java scope inner-classes lifetime

我需要解释为什么以下代码无法编译(在范围和生命周期方面):

class ClassInMethod
{
   public static void main(String[] args)
   {
      int local = 1;

      class Inner
      {
         public void method()
         {
             System.out.println(local);
         }
      }
   }
}

认为是因为: 使用但未在内部类中声明的任何局部变量必须声明为“final”。因此,在此示例中,'local'必须声明为final,因为其范围和生命周期在main方法中结束(因此需要更改为:final int local = 1;)。

还有其他建议吗?

3 个答案:

答案 0 :(得分:2)

请参阅http://techtracer.com/2008/04/14/mystery-of-accessibility-in-local-inner-classes/,了解编译器如何使用final技巧解决内部类的问题(即范围和生命周期问题)。

答案 1 :(得分:1)

试着编译它。编译器输出:

ClassInMethod.java:11: local variable local is accessed from within inner class; needs to be declared final
    System.out.println(local);
                       ^
1 error

答案 2 :(得分:1)

您必须创建局部变量final的原因是Java将其值复制到内部类的实例中。幕后发生的事情是编译器生成的字节码(大致)对应于此:

class ClassInMethod {
    public static void main(String[] args) {
        int local = 1;

        // this happens when you do: new Inner()
        ClassInMethod_main_Inner inner = new ClassInMethod_main_Inner();
        inner.local = local;
    }
}

// the inner class
class ClassInMethod_main_Inner {
    int local;

    public void method() {
        System.out.println(local);
    }
}

如果local不是final,并且您可以在实例化Inner和调用method()之间更改其值,则调用{{1}将使用method()的旧值。这可能是不正确的行为。强制local的原因是使内部类的行为更直观。

(有些语言没有这个限制,但它需要编译器和运行时的明确支持.Java的开发人员到目前为止还没有决定专心致力于实现它。)