1. 構造器
1.1 構造器的核心意義
1.1.1? 對象初始化
- 構造器在創建對象 (new) 時自動調用, 用于初始化對象的狀態 (如設置字段初始值, 分配資源等)
- 無構造器時:?字段為默認值(
0
/null
/false
) 有構造器:確保對象創建后即處于有效狀態
- 無構造器時:?字段為默認值(
- 構造器在創建對象 (new) 時自動調用, 用于初始化對象的狀態 (如設置字段初始值, 分配資源等)
1.1.2? 強制初始化
- 通過有參構造器強制要求調用方必須提供必要參數, 避免對象狀態不完整?(如必須傳入用戶ID)。
1.1.3? 代碼復用(重載機制)
- 通過
this()
調用其他構造器,減少重復代碼(構造器重載時)。
- 通過
1.1.4? 封裝控制(支持不可變的對象設計)
- 私有構造器可限制對象創建 (單例模式, 工具類禁止實例化)
1.2 構造器的基礎語法
- 代碼示例
public class Car {private String brand;private int price;//無參構造public Car() {this.brand = "UNknow";this.price = 0;}//有參構造1public Car(String brand, int price) {this.brand = brand;this.price = price;}//有參構造2public Car(String brand) {this.brand = brand;} }
1.3 構造器的關鍵特性
- a. 命名: 必須與類名完全相同
- b. 無返回值: 不可聲名返回類型(連void都不行)
- c. 自動調用: new 關鍵字自動調用
- d. 默認構造器: 未顯式定義構造器時編譯器會自動生成一個無參構造器; 定義后則不會再生成
- e. 支持重載: 可定義多個參數不同的構造器
1.4 進階用法
1.4.1 構造器鏈
- 使用 (this) 關鍵字調用本類其他構造器(必須放在第一行)
- 代碼示例:
//有參構造1public Car(String brand, int price) {this.brand = brand;this.price = price;}//有參構造2public Car(String brand) {this(brand, 100000);//調用上面的雙參構造器}
1.4.2 父類構造器調用
- 子類構造器必須調用父類構造器(顯式或隱式)?使用??
super(...) (
必須第一行) 1.4.2.1?可以不寫 super() 的情況:
- 父類存在無參構造器時 (顯式定義或編譯器自動生成), 子類構造器會隱式調用super() ,?此時無需顯式寫出, 編譯器會自動在第一行插入super()? ? ? ?
class Parent {// 編譯器自動生成默認無參構造器:Parent() {} }class Child extends Parent {// 編譯器自動添加:super();public Child() {System.out.println("Child構造器");} }
1.4.2.2?必須寫 super() 的情況?
- a. 父類沒有無參構造器
- 若父類定義了有參構造器且未定義無參構造器時, 編譯器不會生成默認無參構造器
子類必須顯式調用父類的某個帶參構造器,否則編譯報錯。
- b. 父類構造器有重載時需要明確指定
- 若父類有多個構造器, 子類需要通過 super()? 來選擇調用哪一個
class ElectricCar extends Car{private int battery;public ElectricCar(String brand , int price , int battery){super(brand ,price);//先初始化父類(調用父類構造器)this.battery=battery;} }class GasCar extends Car{private int gas;public GasCar (String brand , int price , int gas){super(brand);this.gas=gas;} }
- a. 父類沒有無參構造器
1.4.2.3 特殊規則
- 1.?
this()
?和?super()
?不能共存- a.?若子類構造器第一行用
this(...)
調用本類其他構造器,則不能再寫super()
。 - b.?被調用的本類構造器最終仍需調用
super(...)
class GasCar extends Car {private int gas;public GasCar() {this(100);//// 調用GasCar類的其他構造器}public GasCar(int gas) {super("車車");} }
- a.?若子類構造器第一行用
- 2.?繼承鏈的頂端是?
Object
- 所有類的終極父類是
Object
,其有無參構造器Object()
,因此最頂層的super()
調用總是安全的
- 所有類的終極父類是
- 1.?
- 子類構造器必須調用父類構造器(顯式或隱式)?使用??
1.4.3?私有構造器應用場景
1.4.3.1 單例模式: 全局唯一實例
public class Parents {private static final Parents Child = new Parents();//創建全局唯一實例private Parents(){// 私有構造器}public static Parents getInstance(){return Child;//返回唯一的實例} }
1.4.3.2 工具類: 禁止實例化 (Math類等)
public class StringUtils {private StringUtils() {} // 防止 new StringUtils()public static boolean isEmpty(String s) { ... } }
1.4.4 初始化順序
- 對象創建時的執行順序:
- 父類靜態塊 -> 子類靜態塊 -> 父類字段初始化 -> 父類構造器 -> 子類字段初始化 -> 子類構造器
1.5 常見問題
- Q:?為什么構造器不能有返回值?
- ???????A:?構造器隱含返回新對象,聲明返回值會導致編譯器將其視為普通方法。
- Q:?構造器能被
static
/final
修飾嗎?- ???????A: 不能!?構造器屬于對象初始化機制,與類級別(
static
)和繼承(final
)無關。
- ???????A: 不能!?構造器屬于對象初始化機制,與類級別(
- Q:?子類如何調用父類帶參構造器?
- ???????A: 通過super() 顯式調用, 否則編譯器會自動調用父類的無參構造器
- Q:?為什么構造器不能有返回值?
2. 靜態工廠方法
- s
- s
- s
- s
- s
- s
- s
- s
- s
- s
- s
- s
- s
- s
- s
- s
- s
- s