1. Static(能夠修飾成員變量、成員方法、內部類,不能修飾構造器)java
靜態變量可用來在實例之間進行通訊或跟蹤該類實例的數目。Java沒有全局變量,靜態變量有點相似於其餘語言的全局變量。靜態變量只依附於類,對於不是private類型的靜態變量,能夠在該類外直接用類名調用:Count.Counter++;this
null對象能夠訪問它所屬的類的類成員。spa
(1)在類中,用static聲明的成員變量爲靜態成員變量,或者叫作:類屬性,類變量。指針 ①它爲該類的公用變量,屬於類,被該類的全部實例共享,在類被載入時被顯式初始化;code ②對於該類的全部對象來講,static成員變量只有一份。被該類的全部對象共享;對象 ③可使用「對象.類屬性」來調用,不過,通常都是用「類名.類屬性」;blog ④static變量置於方法區中。內存 (2)用static聲明的方法爲靜態方法table ①不須要對象,就能夠調用(類名.方法名)class ②在調用該方法時,不會將對象的引用傳遞給它,因此在static方法中不可訪問非static的成員。 |
系統只初始化static變量仍是全部成員變量?在類加載時初始化static變量,在類的初始化時完成全部成員變量的初始化(先static後成員變量)
靜態方法的編寫與使用時應該注意下列問題:
(1) 靜態方法的調用不是經過實例對象進行的。因此在靜態方法中沒有this指針,不能訪問所屬類的非靜態變量和方法,只能訪問方法體內定義的局部變量、本身的參數和靜態變量
(2) 子類不能重寫父類的靜態方法,但在子類中能夠聲明與父類靜態方法相同的方法,從而將父類的靜態方法隱藏。另外子類不能把父類的非靜態方法重寫爲靜態的。
(3)main()方法是一個靜態方法。由於它是程序的入口點,這可使JVM不建立實例對象就能夠運行該方法。
Static變量從屬於類,存於類的static區,無static修飾的變量從屬於對象。
2. 靜態初始化塊
一個類中,不屬於任何方法體而且以static關鍵字修飾的語句塊,稱爲靜態語句塊。由於靜態語句塊經常使用來進行類變量的初始化,因此也稱爲靜態初始化程序塊。static定義初始化塊,初始化塊有順序,位置靠前先執行。語法以下:
[修飾符]{ // 初始化塊的可執行代碼(定義局部變量,調用其餘對象方法,分支,循環等) } |
若是有修飾符則只能是static,稱爲靜態初始化塊。沒有修飾符爲普通初始化塊。建立java對象時,系統老是先調用該類裏定義的初始化塊。初始化塊雖然也是java類的一種成員,但它沒有名字,沒有標識符,所以沒法經過類、對象來調用初始化塊。初始化塊只在建立java對象時隱式執行,並且在執行構造器以前執行。
初始化塊和構造器之間的差別:
當java建立一個對象時,系統先爲該對象的全部實例屬性分配內存(前提是該類已經被加載過了),接着程序開始對這些實例屬性執行初始化,其初始化順序是:先執行初始化塊或聲明屬性時指定的初始值,再執行構造器裏指定的初始值。 |
初始化是一段固定執行的代碼,它不能接受任何參數。所以初始化塊對同一個類全部對象所進行的初始化處理徹底相同。 |
初始化塊的基本用法:若是有一段初始化處理代碼對全部對象徹底相同,且無須接受任何參數,就能夠把這段初始化處理代碼提取到初始化塊中。 |
static初始化塊:
類初始化塊,系統在類初始化階段執行靜態初始化塊,而不是在建立對象時,所以靜態初始化塊老是比普通初始化塊先執行。
// JDK 8
class Root{ static { System.out.println("Root static 初始化塊"); } // end static
{ System.out.println("Root 普通初始化塊"); } // end
public Root(){ System.out.println("Root 的無參構造器"); } // end constructor
} // end Root
class Mid extends Root{ static { System.out.println("Mid static 初始化塊"); } // end static
{ System.out.println("Mid 普通初始化塊"); } // end
public Mid(){ System.out.println("Mid 的無參構造器"); } // end constructor
public Mid(String msg){ System.out.println("Mid 的帶參構造器,參數值爲 " + msg); } // end constructor
} // end Mid
class Leaf extends Mid{ static { System.out.println("Leaf static 初始化塊"); } // end static
{ System.out.println("Leaf 普通初始化塊"); } // end
public Leaf(){ super("Leaf 調用父類構造器"); System.out.println("Leaf 的無參構造器"); } // end constructor
} // end Leaf
public class Test { public static void main(String[] args) { new Leaf(); new Leaf(); } // end main
} // end Test
output:
Root static 初始化塊
Mid static 初始化塊
Leaf static 初始化塊
Root 普通初始化塊
Root 的無參構造器
Mid 普通初始化塊
Mid 的帶參構造器,參數值爲 Leaf 調用父類構造器
Leaf 普通初始化塊
Leaf 的無參構造器
Root 普通初始化塊
Root 的無參構造器
Mid 普通初始化塊
Mid 的帶參構造器,參數值爲 Leaf 調用父類構造器
Leaf 普通初始化塊
Leaf 的無參構造器
當JVM第一個主動使用某個類時,系統會在類準備階段爲該類的全部靜態屬性分配內存;在初始化階段則負責初始化這些靜態屬性,初始化靜態屬性的就是執行類初始化代碼或者聲明類屬性時指定的初始值,它們的執行順序與源代碼中排列順序相同。
(1)若是但願加載後,對整個類進行某些初始化操做,可使用static初始化塊; (2)是在類初始化時執行,不是在建立對象時執行; (3)靜態初始化塊中不能訪問非static成員; (4)執行順序:上溯到Object類,先執行Object的靜態初始化塊,再向下執行子類的靜態初始化塊,直到咱們的類的靜態初始化塊爲止。 |