請看下面代碼,無法通過編譯,問題出在那?
package demo; public class Test { public static void main(String[] args){ Foo obj1=new Foo(); } } class Foo( ){ int value; public Foo(int initValue){ value=initValue; } }
你可以得到什么結論?
結論:如果類提供一個自定義的方法,系統將不再提供默認方法。
JAVA字段初始化規律:
如果一個類中既有初始化塊,又有構造方法,同時還設定了字段的初始值,誰說了算?
package demo; class InitializeBlockClass { { field=200; } public int field=100; public InitializeBlockClass(int value){ this.field=value; } public InitializeBlockClass(){ } }
結論:
這是一個生造出來展示Java語法特性的示例類,在實際開發中不要這樣寫代碼,應該盡量保證一個字段只初始化一次!
用上面的類,思考輸出的結果:
public static void main(String[]args){ InitializeBlockClass obj=new InitializeBlockClass(); System.out.println(obj.field); obj=new InitializeBlockClass(300); System.out.println(obj.field); }
結論:
(類字段的初始化順序) 執行類成員定義時指定的默認值或類的初始化塊,到底執行哪一個要看哪一個“排在前面”。 執行類的構造函數。 類的初始化塊不接收任何的參數,而且只要一創建類的對象,它們就會被執行。因此,適合於封裝那些“對象創建時必須執行的代碼”。
請運行TestStaticInitializeBlock.java示例,觀察輸出結果,總結出“靜態初始化塊的執行順序”。
class Root { static{ System.out.println("Root的靜態初始化塊"); } { System.out.println("Root的普通初始化塊"); } public Root() { System.out.println("Root的無參數的構造器"); } } class Mid extends Root { static{ System.out.println("Mid的靜態初始化塊"); } { System.out.println("Mid的普通初始化塊"); } public Mid() { System.out.println("Mid的無參數的構造器"); } public Mid(String msg) { //通過this調用同一類中重載的構造器 this(); System.out.println("Mid的帶參數構造器,其參數值:" + msg); } } class Leaf extends Mid { static{ System.out.println("Leaf的靜態初始化塊"); } { System.out.println("Leaf的普通初始化塊"); } public Leaf() { //通過super調用父類中有一個字符串參數的構造器 super("Java初始化順序演示"); System.out.println("執行Leaf的構造器"); } } public class TestStaticInitializeBlock { public static void main(String[] args) { new Leaf(); } }
程序運行輸出結果: Root的靜態初始化塊 Mid的靜態初始化塊 Leaf的靜態初始化塊 Root的普通初始化塊 Root的無參數的構造器 Mid的普通初始化塊 Mid的無參數的構造器 Mid的帶參數構造器,其參數值:Java初始化順序演示 Leaf的普通初始化塊 執行Leaf的構造器
靜態初始化執行規律: 靜態初始化塊只執行一次。 創建子類型的對象時,也會導致父類型的靜態初始化塊的執行。