非靜態內部類不能擁有靜態變量 為什么
下面這段代碼,如果Lazyholder沒有static修飾,則編譯不過
class Singleton2 { private static class LazyHolder { private static Singleton2 singleton; } public Singleton2 getInstance() { return LazyHolder.singleton; } }
"非靜態內部類不能擁有靜態變量" ,可以這樣理解,因為JVM類加載的順序為:
java根據需要在運行時把字節碼載入到內存,它分三個步驟:
1、加載:類加載器查找到字節碼(.class文件)並根據這些字節碼創建一個Class對象;
2、鏈接:驗證類中的字節碼,為靜態域分配存儲空間,需要的話同時解析這個類其它類的所有引用;
3、初始化:當類的靜態方法(構造器是特殊的靜態方法)或者非常數靜態域(即不是編譯器常量)被首次引用時,執行靜態初始化塊和初始化靜態數據。
然后才能執行對象創建
如果LazyHolder沒有static,則本質上,它其實是Singleton2的非靜態成員,則他必須在Singleton2對象創建之后才會進行加載,然而問題在於,另一方面根據JVM的加載順序,static 的singleton變量又必須在LazyHolder對象存在之前完成加載,這就矛盾了。
靠,上面的是昨天寫的,今天突然看不懂了。我想了想,更簡單的理解是:
靜態變量是要能夠直接用類名.靜態變量的方式來訪問的,在上面這個例子中,實際上就是Singleton2.LazyHolder.singleton,是這樣去訪問,但是如果LazyHolder不是靜態類,那問題就來了,你會發現singleton無法被訪問了!因為Singleton.LazyHolder就已經不合法了,根本沒法往下走。嗯,我覺得我自己的理解比網上查到的靠譜多了
什么是匿名內部類
實際上匿名內部類是對下面這種寫法的簡化
public class InnerClassLearn { class MyThread extends Thread { private int i = 11; public int value() {return i;} } public Thread thread() {return new MyThread();} public static void main(String[] args) { Thread thread = new InnerClassLearn().thread(); } }
用匿名內部類的方式重寫上面的代碼:
public class InnerClassLearn { public Thread thread() { return new Thread() { private int i = 11; public int value() {return i;} }; } public static void main(String[] args) { Thread thread = new InnerClassLearn().thread(); } }
其中紅色部分就是一個繼承於 Thread類的匿名內部類