JavaScript里有两个容易让初学者混淆的概念:scope chain and closure。
比如说,我想创建10个函数,每个函数依次返回0-9.
1 //wrong: all function refer to global variable i=10
2 var fn_list=[];
3 for(var i=0;i<10;i++){
4 var _tempFn =function(){
5 return i;
6 }
7 fn_list.push(_tempFn);
8 }
9 //right: every function refer to its closure scope variable a
10 var fn_list=[];
11 for(var i=0;i<10;i++){
12 var _tempFn =function(a){
13 return function(){
14 return a;
15 };
16 }
17 fn_list.push(_tempFn(i));
18 }
19
Java里也有两个让初学者容易混淆的概念:nest class and inner class。
nest class就是static inner class,
而inner class就是no-static inner class。没有为什么,sun就是这么定义的。
还是上面得例子,创建10个对象,每个对象的getValue接口依次返回0-9.
1 public class Test {
2 private int noStaticValue;
3 private static int staticValue;
4
5 public Test(int noSV, int sv) {
6 this.noStaticValue = noSV;
7 this.staticValue = sv;
8 }
9
10 public Test(int noSV) {
11 this.noStaticValue = noSV;
12 }
13
14 interface valueHolder {
15 int getValue();
16 }
17
18 class innerClass implements valueHolder {
19 public int getValue() {
20 return noStaticValue;
21 }
22 }
23
24 static class nestClass implements valueHolder {
25 public nestClass(int i) {
26 staticValue = i;
27 }
28
29 public int getValue() {
30 return staticValue;
31 }
32 }
33
34 public static void main(String[] args) {
35 Test context1 = new Test(0, 0);
36 valueHolder[] list = new valueHolder[10];
37 for (int i = 0; i < 10; i++) {
38 list[i] = new Test.nestClass(i);
39 }
40 for (valueHolder obj : list) {
41 System.out.println(obj.getValue());// always print 9
42 }
43 for (int i = 0; i < 10; i++) {
44 list[i] = new Test(i).new innerClass();
45 }
46 for (valueHolder obj : list) {
47 System.out.println(obj.getValue());// print 0-9
48 }
49 }
50 }
可见用inner class可以模拟closure的特性,就是运行时定义class的某些状态。
inner class和nest class之间的区别就是后者是静态类。前者必须通过wrap class的实例来调用new,e.g. new Test().new innerClass。
因为nest class是静态类,所以可以添加static member 或者static method,而inner class 不行。
匿名内部类是inner class的一种特殊形式,所以也不能添加static member 或者static method。