平時開發,很少關係靜態類細節,現在認真學習了一下,做個總結哈。
1. 如果一個類要被聲明爲static的,只有一種情況,就是靜態內部類。
2. 靜態內部類跟靜態方法一樣,只能訪問外部類的靜態的成員變量和方法,不能訪問非靜態的方法和屬性,但是普通內部類可以訪問任意外部類的成員變量和方法。
3. 靜態內部類可以聲明普通成員變量和方法,而普通內部類不能聲明static成員變量和方法。
4. 靜態內部類可以單獨初始化,普通內部類不行,例子如下:
靜態內部類
Inner i = new Outer.Inner();
普通內部類
Outer o = new Outer();
Inner i = o.new Inner();
根本原因:靜態內部類,不持有外部引用,普通內部類,則持有。
5. 加載一個類時,其內部類不會同時被加載。一個類被加載,當且僅當其某個靜態成員(靜態域、構造器、靜態方法等)被調用時發生。
可看如下例子:
public class Outer {
static {
System.out.println("load outer class...");
}
//靜態內部類
static class StaticInner {
static {
System.out.println("load static inner class...");
}
static void staticInnerMethod() {
System.out.println("static inner method...");
}
}
public static void main(String[] args) {
Outer outer = new Outer(); //此刻其內部類是否也會被加載?
System.out.println("===========分割線===========");
Outer.StaticInner.staticInnerMethod(); //調用內部類的靜態方法
}
}
運行結果:
load outer class…
==========分割線==========
load static inner class…
static inner method…
調用構造方法時,外部類Outer被加載,但這時其靜態內部類StaticInner卻未被加載。直到調用該內部類的靜態方法(在分割線以下),StaticInner才被加載。可以做類似的實驗驗證非靜態內部類的情況(普通內部類,只要不被new,那也不會加載)。
根據內部類不會在其外部類被加載的同時被加載的事實,我們可以引申出單例模式的一種實現方式:
public class Singleton {
private Singleton() {}
static class SingletonHolder {
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
這樣做的好處是,可以確保多線程的情況下是安全的,且是唯一的。
因爲,當執行了SingletonHolder.getInstance(), SingletonHolder 類才被加載,instance 變量一次性初始化,後面直接返回的,就是instance對象。