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。