標籤:
看Thinking in Java中內部類的一章,有內部類和靜態內部類,書中把後者叫做嵌套類。常見用法執行個體:
一般內部類(非靜態)
1 public class InnerClassTest { 2 public static void main(final String args[]) { 3 SomeOuter outer = new SomeOuter(); 4 SomeOuter.SomeInner x = outer.new SomeInner(); 5 x.test(); 6 } 7 } 8 9 class SomeOuter {10 public class SomeInner {11 public static final int x = 2;12 13 // public static int y = 2; public static final Integer Z = 2;14 15 public SomeInner() {16 System.out.println("inner constructor");17 }18 19 public void show() {20 System.out.println("Inner show");21 }22 23 public void test() {24 // method in outter class can be invoked directly25 info();26 27 // inner this & outer this28 this.show();29 SomeOuter.this.show();30 }31 }32 33 public void show() {34 System.out.println("Outer show");35 }36 37 public void info() {38 System.out.println("outer info");39 }40 }41 42 class ExtendedInner extends SomeOuter.SomeInner {43 public ExtendedInner(final int x, final SomeOuter outer) {44 outer.super();45 }46 47 }
其中最後的繼承內部類用法有點特殊,因為非靜態內部類含有一個外部類的引用(如SomeOuter.this),因而在內部類的衍生類別中的構造方法也需要提供一個外部類的執行個體並做如上調用。
非靜態內部類中不能含有靜態成員(欄位和方法),但是final修飾的基本類型除外(也許是因為final修飾的基本類型可以作為編譯期常量看待的原因)。
內部類繼承
下面的用法估計更加少見,在衍生類別中對基類的內部類進行繼承。由於衍生類別含有指向基類的引用所以構造內部類時就不用向在外部那樣傳入一個內部類的外部類執行個體引用了。
public class InnerClassTest { public static void main(final String args[]) { SomeOuterComplex xComplex = new SomeOuterComplex(); xComplex.info(); }}class SomeOuterBasic { protected SomeInner inner; public SomeOuterBasic() { System.out.println("some out basic constructor"); inner = new SomeInner(); } class SomeInner { public SomeInner() { System.out.println("some inner constructor in basic"); } public void say() { System.out.println("some inner basic say"); } } public void info() { inner.say(); }}class SomeOuterComplex extends SomeOuterBasic { class SomeInner extends SomeOuterBasic.SomeInner { public SomeInner() { System.out.println("some inner constructor in complex"); } @Override public void say() { System.out.println("some inner complex say"); } } public SomeOuterComplex() { System.out.println("some out complex constructor"); inner = new SomeInner(); }} 靜態內部類與單例模式/延遲初始化
靜態內部類沒有指向其外部類的引用,因而不能訪問其外部類的非靜態欄位(即執行個體欄位),和一般的類用法最像。當在介面中使用靜態內部類時,則可以實現在介面中“放置”一定的代碼。
public class InnerClassTest { public static void main(final String args[]) { DummyInterface.DoSome.say(); Outer.Inner x = new Outer.Inner(); x.inc(); x.inc(); Singleton.otherThings(); Singleton xSingleton = Singleton.getInstance(); xSingleton.importantThings(); }}class Outer { public Outer() { System.out.println("constructor of Outer"); } public static class Inner { private static String name = "Inner Static Class"; private Integer instanceInteger; public Inner() { instanceInteger = 0; System.out.println("constructor inner: " + name); } public void inc() { instanceInteger++; System.out.println(instanceInteger); } }}interface DummyInterface { class DoSome { public static void say() { System.out.println("say from DoSome"); } static { System.out.println("code running in an interface"); } }}class Singleton { private static class Holder { static { System.out.println("static construct in Singleton.Holder"); } public static Singleton instance = new Singleton(); } private Singleton() { System.out.println("private singleton constructor"); } public static Singleton getInstance() { return Holder.instance; } public static void otherThings() { System.out.println("other things"); } public void importantThings() { System.out.println("instance important things"); }}
可以用來作為延遲初始化和單例模式,靜態內部類在沒有使用時靜態初始化本分不會進行,但使用到時才會初始化,而且這個機制是JVM保證的,即使在並發情況下依然能夠正確運行(因為JVM必須考慮並發時多線程同時對一個類的初次使用的發生)。
Java:內部類