这来自早期版本的Java内部类规范。
链接腐烂的官方规范URL(例如从VM spec
2.14中引用)已消失:http
:
//java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html
不过,可以在Wayback机器上获得1999年1月17日的快照,相应的规范部分为对局部变量的引用。
事情的工作方式描述如下(我将最相关的语句标记为粗体):
块局部的类定义可以访问局部变量。这使编译器的工作复杂化。这是本地类的先前示例:
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(); }为了使局部变量对内部类的方法可见,编译器必须将变量的值复制到内部类可以访问它的位置。只要在各处都产生相同的值,对同一变量的引用就可以在不同的地方使用不同的代码序列,因此该名称在其作用域的所有部分中始终表示相同的变量。
按照约定,将局部变量(例如
array)复制到val$array内部类的私有字段中。(因为array是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 }


