前言
今天在重寫java的過程中,學到static這塊,就簡單對其做個總結和歸納。
static 是靜態的含義,在java中,可以用來修飾成員變量、成員方法以及代碼塊。
靜態變量
被static修飾的普通成員變量就是靜態變量,普通的成員變量是隨着對象的創建而加載,而靜態變量只隨着類加載而加載一次,且當靜態變量的權限大於private時,可以直接通過類名.變量名進行調用。
以下通過定義一個員工類進行說明:
//這是一個員工類
public class EmployeeStatic {
//這是一個普通成員變量
public String name;
//這是一個靜態變量
public static String company;
}
public static void main(String[] args) {
EmployeeStatic02 e = new EmployeeStatic02();
//對於普通成員變量,則需要先創建一個員工對象,再對其進行調用以及賦值
e.name = "張三";
EmployeeStatic02 e2 = new EmployeeStatic02();
e2.name = "里斯";
//直接通過類名.變量名,對靜態變量進行賦值以及調用
EmployeeStatic02.company = "AWM公司";
System.out.println("員工姓名:" + e.name + " 公司:" + EmployeeStatic02.company);
System.out.println("員工姓名:" + e2.name + " 公司:" + EmployeeStatic02.company);
System.out.println("----------------");
//直接通過 員工1.變量名,對靜態變量進行賦值以及調用
e.company = "阿里";
System.out.println("員工姓名:" + e.name + " 公司:" + e.company);
System.out.println("員工姓名:" + e2.name + " 公司:" + e2.company);
System.out.println("----------------");
//直接通過 員工2.變量名,對靜態變量進行賦值以及調用
e2.company = "騰訊";
System.out.println("員工姓名:" + e.name + " 公司:" + e.company);
System.out.println("員工姓名:" + e2.name + " 公司:" + e2.company);
}
運行結果:
員工姓名:張三 公司:AWM公司
員工姓名:里斯 公司:AWM公司
——————
員工姓名:張三 公司:阿里
員工姓名:里斯 公司:阿里
———————
員工姓名:張三 公司:騰訊
員工姓名:里斯 公司:騰訊
可以看出,無論是通過類名.靜態變量進行調用賦值,還是通過對象.靜態變量進行調用賦值,所以對其實現的實例對象的的靜態變量值都會發生改變。
拓展:
注1:訪問權限:public>protected>default(一般省略)>private。
注2: static + final所修飾的變量爲全局變量(相當於常量),再定義時對其進行賦值,且值不可改變
eg:public static final NUM = 1;
靜態方法
被static修改的方法是靜態方法,和靜態變量一樣,普通成員方法的調用需要依賴於對象,而靜態方法可以直接通過調用類進行使用,權限大於private時,可以直接通過類名.變量名進行調用。
以下也通過一個實例對其進行說明:
首先先定義倆個方法,一個普通成員方法,一個靜態方法
public class StaticMethod {
public void method1() {
System.out.println("這是一個普通方法");
}
public static void methodStatic() {
System.out.println("這是一個靜態方法");
}
}
public static void main(String[] args) {
StaticMethod s = new StaticMethod();
//對象名.成員方法 進行調用
s.method1();
// 類名.靜態方法、類目.靜態變量的方式進行調用
StaticMethod.methodStatic();
}
輸出結果:
這是一個普通方法
這是一個靜態方法
以上就是對靜態方法的簡單調用
拓展:
在普通的成員方法中,可以使用成員變量和靜態變量,而在靜態方法中,只可以使用靜態變量,不能使用成員變量
public class StaticDemo4 {
public int num = 10;
public static int staticNum = 20;
public void method1() {
//普通成員方法中調用普通成員變量
System.out.println(num);
//普通成員方法中調用靜態變量
System.out.println(staticNum);
}
public static void methodStatic() {
//靜態方法中調用靜態變量
System.out.println(staticNum);
//靜態方法中調用普通成員變量(會報錯)
//System.out.println(num); //錯誤寫法,靜態方法中不允許調用普通成員變量
}
}
因爲在一個方法的加載過程中,會先加載static的變量和方法,再進行調用普通的成員變量和方法,首先加載了靜態變量,然後再加載靜態方法,加載過程中,靜態變量已經加載成功,所以可以調用成功,但普通成員變量還沒創建加載,所以不能調用。
靜態代碼塊
static代碼塊在類中可以有多個,且位置不固定,沒有先後順序。但在類的加載中,只會執行一次,且是最先執行的。如果有多個,則是根據出現的先後順序進行依次執行。
public class StaticMethodDemo02 {
static {
System.out.println("這是第一個靜態代碼塊");
}
public static void main(String[] args) {
System.out.println("這是一個主方法");
}
static {
System.out.println("這是第二個靜態代碼塊");
}
}
執行結果:
這是第一個靜態代碼塊
這是第二個靜態代碼塊
這是一個主方法
由執行結果可以看出以上結論的正確性。
拓展:
帶有繼承的靜態代碼塊,構造代碼塊以及類的構造方法直接加載順序又是如何呢?
可以通過以下實例得出結論
public class FU {
public FU() {
System.out.println("FU中的構造方法");
}
static {
System.out.println("FU方法中的靜態代碼塊");
}
{
System.out.println("FU方法中構造代碼塊");
}
}
public class Zi extends FU {
int num = 10;
static int staticnum = 20;
public Zi() {
System.out.println("Zi中的構造方法"+"..."+num);
}
static {
System.out.println("Zi方法中的靜態代碼塊"+"..."+staticnum);
// System.out.println("Zi方法中的靜態代碼塊"+"..."+num); // 報錯
}
{
System.out.println("Zi方法中構造代碼塊"+"..."+num);
}
public static void main(String[] args)
{
new Zi();
}
}
運行結果:
FU方法中的靜態代碼塊
Zi方法中的靜態代碼塊…20
FU方法中構造代碼塊
FU中的構造方法
Zi方法中構造代碼塊…10
Zi中的構造方法…10
結論1:在帶有繼承的靜態代碼塊,構造代碼塊以及類的構造方法直接加載順序,父類中靜態代碼塊>子類中靜態代碼塊>父類中的構造代碼塊>父類中構造方法>子類中構造代碼塊>子類中構造方法
結論2:根據子類三行代碼的執行順序,可以得到非繼承關係中,靜態變量>靜態代碼塊>成員變量>構造代碼塊(成員方法)>構造方法
以上就是小楓我現如今對static這塊的掌握內容,日後如果有其他更深層次的學習,再進行補充。
如果其他小夥伴對這塊有不一樣或者新的見解,歡迎評論互相學習。