错误:从内部类中访问局部变量a;需要宣布最终

时间:2014-12-11 18:34:30

标签: java

class Outer
{
    void m1()
    {
        int a=12;
        class Inner
        {
            void show()
            {
                System.out.println(a);
            }
        }
        new Inner().show();
    }

}

这里当我编译这段代码时,我得到的错误是局部变量a是从内部类中访问的;需要宣布最终。但是这里“int a”是一个局部变量,所以为什么我们需要在内部类中声明为final。

2 个答案:

答案 0 :(得分:3)

如果局部变量在内部类中使用,则需要声明它final。对于要在这样的内部类中使用的局部变量,后台的Java接受局部变量的副本并使其成为隐式实例变量,以便内部类可以访问它。因为它是副本,如果值更改,副本可能是错误的。因此,编译器会强制您将其设为final

请注意,在Java 8中,这将编译,因为a是“有效的最终” - 未声明为final,但在初始化后从未更改过。

Section 8.1.3 of the JLS州:

  

在内部类中使用但未声明的任何局部变量,形式参数或异常参数必须声明为final或者是有效的final(§4.12.4),否则在尝试使用时会发生编译时错误。

Section 4.12.4 of the JLS州:

  

如果局部变量或方法,构造函数,lambda或异常参数未声明为final,则它实际上是final,但它永远不会作为赋值运算符的左手操作数(第15.26节)或作为前缀的操作数发生或后缀增量或减量运算符(§15.14,§15.15)。

     

此外,如果满足以下所有条件,则声明缺少初始值设定项的局部变量实际上是最终的:

     
      
  • 未宣布为最终版。

  •   
  • 每当它作为赋值运算符的左操作数出现时,它肯定是未赋值的,并且在赋值之前没有明确赋值;也就是说,它绝对是未赋值的,并且在赋值的右手操作数之后没有明确赋值(§16(Definite Assignment))。

  •   
  • 它永远不会作为前缀或后缀的操作数增加或减少运算符。

  •   

答案 1 :(得分:0)

您可以通过将最终变量声明为数组来轻松解决此问题:

final int x[] = {2};

然后从内部类中设置数组值(方法调用返回值的示例):

x[0] = methodcall();

或(仅将值设置为 10 的示例):

x[0] = 10;