
“嗨,阿米戈!这里有一些更多的信息给你。”
“我已经告诉过你了,编译器实际上把所有的匿名类都转换成了普通的内部类。”
“是的。我什至记得他们的名字都是数字:1、2、3,等等。”
“完全正确。但这里还有另一个细微差别。”
“如果一个类在方法内部声明并使用它的任何变量,那么对这些变量的引用将被添加到生成的类中。你自己看看。”
“我们从这个开始:”
编译前:
class Car {
public ArrayList createPoliceCars(int count) { ArrayList result = new ArrayList(); for(int i = 0; i < count; i++) { final int number = i; result.add(new Car() { public String toString() { return ""+number; } }); } return result; }
}
“编译器生成这个:
编译后:
class Car {
public ArrayList createPoliceCars(int count) { ArrayList result = new ArrayList(); for(int i = 0; i < count; i++) { final int number = i; result.add(new Anonymous2 (number)); } return result; }
class Anonymous2 { final int number; Anonymous2(int number) { this.number = number; } public String toString() { return ""+ number; } }
}
“你明白了吗?内部类不能改变方法的局部变量,因为当内部类的代码被执行时,我们可能会完全退出方法。”
“现在是第二点。toString() 方法使用传递的变量。要实现这一点,有必要:”
A)将其保存在生成的类中
B)将其添加到构造函数中。
“明白了。在方法内部声明的类总是使用变量的副本。”
“确切地!”
“那么为什么变量必须是最终的,以及为什么它们不能被改变是有道理的。如果你实际上是在使用副本而不是原件,用户将不明白为什么他不能改变变量的值,这意味着我们只需要禁止他改变它们。”
“是的,将变量声明为 final 似乎是一个很小的代价,以换取编译器为您生成一个类,将其传递给方法,并保存您要使用的所有方法变量。”
“我同意,匿名本地班还是超级爽的。”
“如果我在一个方法中声明一个本地类,并在其中使用该方法的变量,编译器是否也会将它们添加到该类中?”
“是的,它会将它们添加到类及其构造函数中。”
“我也这么想。”
GO TO FULL VERSION