正如其他人在这里所说的,局部变量必须是最终才能被内部类访问。
这里是(基本上)这是为什么?如果你写了下面的代码(长的答案,但是,在底部,你可以得到短版:-):
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
final int x;
Foo foo;
x = 42;
foo = new Foo()
{
public void bar()
{
System.out.println(x);
}
};
foo.bar();
}
}
编译大致翻译这样的:
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
final int x;
Foo foo;
x = 42;
class $1
implements Foo
{
public void bar()
{
System.out.println(x);
}
}
foo = new $1();
foo.bar();
}
}
,然后这样的:
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
final int x;
Foo foo;
x = 42;
foo = new $1(x);
foo.bar();
}
private static class $1
implements Foo
{
private final int x;
$1(int val)
{
x = val;
}
public void bar()
{
System.out.println(x);
}
}
}
终于到这一点:
class Main
{
public static void main(String[] args)
{
final int x;
Main$Foo foo;
x = 42;
foo = new Main$1(x);
foo.bar();
}
}
interface Main$Foo
{
void bar();
}
class Main$1
implements Main$Foo
{
private final int x;
Main$1(int val)
{
x = val;
}
public void bar()
{
System.out.println(x);
}
}
重要的是它将构造函数添加到$ 1的位置。试想一下,如果你能做到这一点:
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
int x;
Foo foo;
x = 42;
foo = new Foo()
{
public void bar()
{
System.out.println(x);
}
};
x = 1;
foo.bar();
}
}
你会认为foo.bar()将打印出1,但它实际上打印出42.通过要求局部变量是最终不能出现这种混乱的局面。
太糟糕了,java需要在这里做决定。编译器明显知道局部变量没有改变,所以不应该要求编码器确认。如果匿名类写入局部变量,编译警告就足够了。糟糕的坏设计选择。 – irreputable 2010-07-14 23:24:13
可能的重复[为什么只有最后一个变量可以在匿名类中访问?](http://stackoverflow.com/questions/4732544/why-are-only-final-variables-accessible-in-anonymous-class) – vaxquis 2015-07-01 14:23:45