这来自早期版本的 Java 内部类规范。
官方规范 URL,例如来自VM 规范 2.14的引用已因链接腐烂而消失:http: //java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html
1999 年 1 月 17 日的快照可以在 Wayback 机器上获得,相应的规范部分是References to local variables。
事情应该如何工作的方式描述如下(我将最相关的声明标记为粗体):
块本地的类定义可以访问局部变量。这使编译器的工作变得复杂。这是本地类的上一个示例:
Enumeration myEnumerate(final Object array[]) {
class E implements Enumeration {
int count = 0;
public boolean hasMoreElements()
{ return count < array.length; }
public Object nextElement() {
{ return array[count++]; }
}
return new E();
}
为了使局部变量对内部类的方法可见,编译器必须将变量的值复制到内部类可以访问它的地方。对同一个变量的引用可能在不同的地方使用不同的代码序列,只要在任何地方都产生相同的值,因此该名称在其范围的所有部分中始终显示为引用同一个变量。
按照惯例,局部变量 likearray
被复制到val$array
内部类的私有字段中。(因为array
is final
,这样的副本永远不会包含不一致的值。) ...
你看,语言设计者希望每次创建这样的副本时复制的局部变量的值都是“一致的”。他们的动机很可能是开发人员不必担心查看内部类的副本以检查它是否已被更改:
Enumeration myEnumerate(Object array[], int copy) { // array not final, let's see...
for (int i = 0, i < 2; i++ ) { // loop to have several copies
class E implements Enumeration {
int count = 0;
public boolean hasMoreElements()
{ return count < array.length; }
public Object nextElement() {
{ return array[count++]; }
} // we hope to be done with E... oh no
array = null; // not final => can change
if (i == copy) {
return new E(); // we need to look outside of E
// to figure value of array it uses
}
}
return null;
}
请注意,尽管规范示例使用命名类,但同样的推理也适用于匿名类:
// ...
for (int i = 0, i < 2; i++ ) { // loop to have several copies
if (i == copy) {
return new Enumeration() {
int count = 0;
public boolean hasMoreElements()
{ return count < array.length; }
public Object nextElement() {
{ return array[count++]; }
} // we hope to be done... oh no
}
array = null; // not final => can change
}