2012-04-26 102 views
14

为什么我需要声明local variablefinal如果在方法中定义的我的Inner class需要使用它?内部类和局部变量

实施例:

class MyOuter2 { 

private String x = "Outer2"; 

void doStuff() { 
    final String y = "Hello World"; 

    final class MyInner { 

     String z = y; 

     public void seeOuter() { 
      System.out.println("Outer x is "+x); 
      System.out.println("Local variable is "+y); 
      MyInner mi = new MyInner(); 
      mi.seeOuter(); 
     } 
    } 
} 

}

为什么字符串y需要是一个最终恒定?它如何影响?

+0

看看这个讨论是否有助于http://techtracer.com/2008/04/14/mystery-of-accessibility-in-local-inner-classes/ – kosa 2012-04-26 17:52:59

+0

可能的重复[无法引用内部的非最终变量在不同的方法中定义的内部类](http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a- differen) – 2012-04-26 17:53:59

+0

[关于Java中局部最终变量的问题](http://stackoverflow.com/questions/5947352/question-about-local-final-variable-in-java)。 – Lion 2012-04-26 18:33:29

回答

13

答案是两者在不同的范围。所以这个变量在内部类访问它之前可能会改变。使它最终防止这一点。

+2

这在java 8中已经改变了:http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html#accessing-members-of-an-enclosing-class – ohcibi 2014-03-20 20:38:00

3

我认为这是为了防止程序员会犯错误。这样,编译器会提醒程序员,当您离开该方法时,该变量将不再可用。这对循环很重要。想象一下这样的代码:

public void doStuff() 
{ 
    InnerClass cls[] = new InnerClass[100]; 
    for (int i = 0; i < 100; ++i) 
    { 
     cls[i] = new InnerClass() 
     { 
      void doIt() 
      { 
       System.out.println(i); 
      } 
     }; 
    } 
} 

doIt()方法被调用时,究竟会被打印?循环时更改了i。 为了防止这种混淆,您必须将变量复制到局部变量或创建变量final,但是您将无法循环。

1

你的内部类是终局的,所以你不应该能够从您的最终实体内任何修改。

15

局部变量总是生活在堆栈上,此刻的方法是在所有的局部变量都没有了。

但是,即使在方法结束后,你的内部类对象可能在堆上(假设一个实例变量持有引用),所以在这种情况下,它不能访问你的局部变量,除非你标记它们作为最终

7

这是因为在函数内部的内部类实际上使局部变量的副本,因为局部变量可以在函数调用后销毁,而本地类的实例仍然存在。为了使局部变量的两个副本始终具有相同的值(使它们看起来相同),必须将该变量声明为final。

0

根据Java的内存模型使用最后一个变量保证了最终的变量总是被初始化的。 当我们尝试在没有初始化的情况下使用本地变量时,会出现错误。 使用final来初始化已使用的局部变量的内部类。