Java 內部類與 C++ 巢狀類雖同源,卻因隱式持有外部類引用而大異其趣。初學者常覺多餘,實則是設計者用心良苦的結晶——它能實現多重繼承效果、封裝實現細節、優雅解決回調問題。掌握內部類,是邁向 Java 高階開發的必經之路。
public class Goods {
private class Content implements Contents { // 完全隱藏
private int i = 11;
public int value() { return i; }
}
protected class GDestination implements Destination { // 受保護
private String label;
private GDestination(String whereTo) { label = whereTo; }
public String readLabel() { return label; }
}
public Destination dest(String s) { return new GDestination(s); }
public Contents cont() { return new Content(); }
}
客戶端僅見 Contents、Destination 介面,Content、GDestination 類名完全不對外暴露——極致的封裝。
非靜態內部類實例隱式持有外部實例引用,可直接存取外部類 所有成員(含 private):
public class Goods {
private double valueRate = 2.0; // 外部私有欄位
private class Content implements Contents {
private int i = 11;
public int value() { return (int)(i * valueRate); } // 直接存取 valueRate
}
}
編譯器自動在構造器傳入外部引用,這也是創建非靜態內部類實例必須先有外部實例的原因。
內外部同名成員時,用 OuterClass.this.field 明確指向外部成員。
new Outer.StaticInner()public class Goods1 {
public Destination dest(String s) {
class GDestination implements Destination { // 方法內部類
private String label;
GDestination(String whereTo) { label = whereTo; }
public String readLabel() { return label; }
}
return new GDestination(s);
}
}
if 區塊內)// 實作介面
new Contents() {
private int i = 11;
public int value() { return i; }
};
// 繼承類別(含建構器參數)
new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(0); }
};
new Interface(){...} 或 new SuperClass(){...}super(params))final)、改為區域類、實例初始化區塊 {...}Java 無多重繼承,但內部類 + 介面 = 多重繼承效果:
// 單一外部類同時實作「可序列化」與「可比較」兩個介面
public class Data implements Serializable {
private class ComparatorImpl implements Comparator { ... }
private class SerializerImpl implements Externalizable { ... }
// 對外暴露介面方法,內部類協同完成
}
從封裝實現、存取外部狀態、模擬多重繼承,到簡化回調代碼,內部類無處不在。下次當你猶豫「要不要拆成獨立類」時,請記住:如果某類只服務於另一個類,且需要其私有狀態,內部類往往是最優雅的答案。