對象創建與銷毀是 Java 程序運行的基石。本文系統講解構造器分類、初始化塊、靜態初始化、默認值保證、可見性、垃圾回收機制、終結器與 try-with-resources、單例/工廠/依賴注入等構造器模式,助你構建高性能、線程安全、易維護的對象創建體系。
類未聲明任何構造器時,編譯器自動生成 public NoArgsConstructor() {}。僅用於簡單類,無初始化邏輯。
public class NoArgConstructor {
public NoArgConstructor() {
// 初始化邏輯
}
}
替換隱式構造器,便於未來擴展參數。
public class ConstructorWithArgs {
private final String required;
private final String optional;
private final int timeout;
// 主構造器 (全參數)
public ConstructorWithArgs(String required, String optional, int timeout) {
this.required = required;
this.optional = optional;
this.timeout = timeout;
}
// 便利構造器鏈式調用主構造器
public ConstructorWithArgs(String required, String optional) {
this(required, optional, 3000); // 默認超時
}
public ConstructorWithArgs(String required) {
this(required, null, 3000);
}
}
鐵律:所有便利構造器最終調用主構造器 (this(...)),確保初始化邏輯單一入口,避免代碼重複與不一致。
public class InitializationBlock {
{ // 非靜態初始化塊
// 邏輯在每次構造器調用前執行,按聲明順序
System.out.println("Instance init block 1");
}
{
System.out.println("Instance init block 2");
}
public InitializationBlock() {
System.out.println("Constructor");
}
}
// 輸出: init 1 → init 2 → Constructor
| 類型 | 默認值 |
|---|---|
| boolean | false |
| byte/short/int/long | 0 / 0L |
| char | \u0000 |
| float/double | 0.0f / 0.0d |
| 引用類型 | null |
初始化順序 (單類):
繼承鏈初始化順序:
public class StaticInitialization {
static {
// 類加載時執行一次,線程安全 (JVM 鎖保護)
System.out.println("Static init 1");
}
static {
System.out.println("Static init 2");
}
// 靜態字段初始化穿插在靜態塊中,按聲明順序
private static final String CONFIG = loadConfig(); // 靜態方法調用
}
<clinit> 方法線程安全,僅執行一次。| 修飾符 | 同包可見 | 子類可見 | 異包非子類可見 | 典型用途 |
|---|---|---|---|---|
| public | ✓ | ✓ | ✓ | 公共 API |
| protected | ✓ | ✓ | ✗ | 繼承體系模板方法 |
| package-private | ✓ | ✗ | ✗ | 模塊內部組件 |
| private | ✗ | ✗ | ✗ | 單例、工廠方法、構建器模式 |
JVM 將堆劃分為 新生代 (Eden + S0 + S1) 和 老年代,採用 Minor GC (新生代) 和 Major/Full GC (全堆)。
-XX:PretenureSizeThreshold)。-XX:MaxTenuringThreshold, 默認 15) 晉升老年代。// 反模式:finalize() 不可靠、延遲、性能差、無順序保證
@Override
protected void finalize() throws Throwable {
try { cleanup(); } finally { super.finalize(); }
}
// 正統替代:AutoCloseable + try-with-resources (Java 7+)
public class ResourceHandler implements AutoCloseable {
private final InputStream in;
public ResourceHandler(Path path) throws IOException { this.in = Files.newInputStream(path); }
@Override
public void close() throws IOException { in.close(); }
}
// 使用
try (ResourceHandler handler = new ResourceHandler(path)) {
// 使用資源
} // 編譯器自動生成 finally { handler.close(); }
結論:禁用 finalize(),資源釋放統一用 AutoCloseable + try-with-resources,確定性、異常安全、可讀性優。
// 饿漢式 (類加載時創建,線程安全、無延遲)
public class EagerSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() { return INSTANCE; }
}
// 懶漢式雙重檢查鎖 (DCL) - Java 5+ volatile 保證可見性
public class LazySingleton {
private static volatile LazySingleton instance;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (instance == null) instance = new LazySingleton();
}
}
return instance;
}
}
// 靜態內部類 (推薦:延遲加載 + 線程安全 + 簡潔)
public class HolderSingleton {
private HolderSingleton() {}
private static class Holder {
static final HolderSingleton INSTANCE = new HolderSingleton();
}
public static HolderSingleton getInstance() { return Holder.INSTANCE; }
}
// 枚舉單例 (最強:防反序列化破壞、防反射攻擊、線程安全)
public enum EnumSingleton {
INSTANCE;
public void doSomething() {}
}
public final class StringUtils {
private StringUtils() { throw new AssertionError("No instances"); } // 防實例化
public static boolean isBlank(String s) { return s == null || s.trim().isEmpty(); }
public static String join(CharSequence delimiter, CharSequence... elements) { ... }
}
final 類 + private 構造器拋異常。// 簡單工廠方法
public class Book {
private Book(String title) { this.title = title; }
public static Book newBook(String title) { return new Book(title); } // 靜態工廠
// 優勢: 有名字、可返回子類/緩存、可返回 Optional
}
// 抽象工廠 (接口隔離具體實現)
public interface BookFactory { Book createBook(); }
public class LibraryFactory implements BookFactory {
public Book createBook() { return new PaperBook(); }
}
public class KindleFactory implements BookFactory {
public Book createBook() { return new KindleBook(); }
}
// 硬編碼依賴 (難測試、難替換)
public class Dependant {
private final DateFormat format = DateFormat.getDateInstance(); // 內部創建
}
// 構造器注入 (推薦:不可變、強依賴顯式、易測試)
public class Dependant {
private final DateFormat format;
public Dependant(DateFormat format) { this.format = format; } // 外部提供
public String format(Date date) { return format.format(date); }
}
// Spring 管理
@Bean
public Dependant dependant() { return new Dependant(DateFormat.getDateInstance()); }
核心思想:依賴向上傳遞,由容器/調用者組裝,實現解耦、可測試、可替換。
Java 對象創建看似簡單,實則蘊含**初始化順序、線程安全、內存管理、設計模式**等深層機制。掌握:
try-with-resources。這些原則不僅是語法規範,更是高質量 Java 代碼的基因。