在 Java 中,內部類是定義在另一個類內部的類。根據定義方式與靜態修飾符的不同,主要分為成員內部類、靜態內部類、局部內部類與匿名內部類。理解它們的加載時機、訪問規則與實例化方式,對於掌握 Java 物件導向設計至關重要。
成員內部類不帶 static 修飾,它依附於外部類的實例。只有在外部類實例化後,才能創建內部類對象。成員內部類不能定義 static 變數與方法(final 常量除外),因為內部類尚未加載,靜態成員無法被即時解析。
class Outer {
class Inner {
int k = 0;
// static int j = 0; // 編譯錯誤
final int z = 0;
void say() { }
}
}
實例化語法:new Outer().new Inner()。
使用 static 修飾的內部類稱為靜態內部類(或巢狀類)。它不依賴外部類實例,可直接通過 Outer.StaticInner 訪問。靜態內部類可以擁有靜態變數與靜態方法,行為類似頂層類。
class Outer {
static class StaticInner {
int k = 0;
static int j = 0;
final int z = 0;
static void staticMethod() { }
void instanceMethod() { }
}
}
調用方式:Outer.StaticInner.staticMethod() 或 new Outer.StaticInner().instanceMethod()。
定義在方法內部的類。它只能在方法執行期間被實例化,且只能訪問方法中被 final 或「實際上 final」修飾的局部變數。局部內部類的聲明順序必須先於使用,因為它在方法中本質上是一個局部變數。
void method() {
final int x = 10;
class LocalInner {
void print() { System.out.println(x); }
}
new LocalInner().print(); // 必須在聲明後使用
}
java.lang.ClassLoader 的核心職責是根據類的全限定名,尋找或生成對應的字節碼,並將其轉換為 java.lang.Class 實例。此外,它還負責加載應用程式所需的資源(圖片、配置文件等)。
getParent():返回父類加載器loadClass(String name):加載指定名稱的類,返回 Class 實例findClass(String name):查找類的具體實現(由子類覆寫)findLoadedClass(String name):查找已加載的類defineClass(byte[] b, int off, int len):將字節碼轉換為 Class 對象(final 方法)resolveClass(Class<?> c):鏈接指定的 Java 類Java 採用雙親委派模型:類加載請求先委派給父加載器,只有父加載器無法完成時,子加載器才會嘗試加載。這保證了核心類庫的安全性與一致性。
public class ClassLoaderDemo {
public static void main(String[] args) {
// 1. 啟動類加載器 - 加載核心類庫 (rt.jar 等)
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (URL u : urls) System.out.println("Bootstrap: " + u);
// 2. 擴展類加載器 - 加載 java.ext.dirs 路徑下的類
System.out.println("Extension: " + ClassLoader.getSystemClassLoader().getParent());
System.out.println("java.ext.dirs: " + System.getProperty("java.ext.dirs"));
// 3. 應用程式類加載器 - 加載 CLASSPATH 指定的類
System.out.println("Application: " + ClassLoader.getSystemClassLoader());
}
}
理解類加載器層級關係,對於解決類衝突、熱部署、模組化開發等進階場景具有關鍵指導意義。