觀察下面代碼
1,如果把第五行的注釋打開則編譯不通過,因為方法內的變量需要是final變量或者事實上的final變量(effectively final)才可以傳入匿名內部類被使用
2,把第五行注釋加上之后,用java8可以編譯通過,此時變量d是事實上的final變量,jvm可以放心地把該變量復制到內部類中
3,為什么需要把d復制一份到內部類?因為test1方法的生命周期比內部類要短,導致test1執行完之后棧內的變量隨着方法棧銷毀而銷毀,此時內部類還存在
4,第二和第三個方法,內部類也引用了外部的變量,但是c和w都分配在堆區,生命周期不受限制,所以不必要復制到內部類里邊
1 public class InnerClassTest { 2 3 void test1() { 4 int d = 2; 5 //d = 3; 6 new Runnable() { 7 @Override 8 public void run() { 9 System.out.println(d); 10 } 11 }; 12 } 13 14 int c = 1; 15 void test2() { 16 c = 2; 17 new Runnable() { 18 @Override 19 public void run() { 20 System.out.println(c); 21 } 22 }; 23 } 24 25 void test3() { 26 W w = new W(); 27 Thread thread = new Thread(new Runnable() { 28 @Override 29 public void run() { 30 w.i = 4; 31 System.out.println(w.i); 32 } 33 }); 34 thread.run(); 35 System.out.println(w.i); 36 } 37 } 38 class W { 39 int i = 2; 40 }