1. 程式人生 > 其它 >15.Java this 關鍵字/static關鍵字/靜態初始化塊

15.Java this 關鍵字/static關鍵字/靜態初始化塊

Java 的 this 關鍵字、static關鍵字、靜態初始化塊

建立物件的過程

  1. 分配物件空間,並將物件成員初始化為 0 或 空
  2. 執行屬性值的顯式初始化
  3. 執行構造方法
  4. 返回物件的地址給相關的變數。

this 關鍵字

注意點

  1. this 關鍵字用於區分區域性變數和成員變數。(就近原則:優先獲取最近的)
  2. 通過 this 可以直接指代成員變數(屬性)。
  3. 通過 this 可以去呼叫類中普通的成員方法。
  4. 通過 this 可以去呼叫構造器。使用 this 關鍵字在一個構造器中去呼叫另一個過載的構造方法,可以避免相同的初始化程式碼。但只能在構造方法中用,且必須位於構造方法程式碼的第一行,否則報錯。
  5. this 不能用於 static 方法中
  6. 在程式產生二義性之處,應用 this 來指明當前物件;
  7. 普通方法中,this 總是指向呼叫該方法的物件。
  8. 構造方法中,this 總是指向正要初始化的物件。

程式碼示例:上方注意點中提到的程式碼

public class TestThis1 {
    int a,b,c;
    // 定義構造方法
    TestThis1(int a,int b){
        this.a = a;
        this.b = b;
    }
    // 構造方法的過載
    TestThis1(int a,int b,int c){
        // 呼叫本類中(上方)兩個引數的構造方法。在一個構造器中呼叫另一個構造器。
        this(a,b);
        this.c = c;
    }
    // 定義普通方法
    void sing(){
        System.out.println("小明同學,小明同學");
    }
    // 定義普通方法
    void eat() {
        // 呼叫本類中的 sing() 方法
        this.sing();
        System.out.println("小明同學,小明同學,你媽媽給你送來了你最喜歡的旺仔牛奶。");
    }

    public static void main(String[] args) {
        // 建立類物件,呼叫類方法(如果自定義了構造方法,則系統就不會自動新增無參構造方法,建立物件時就需要指定是哪個構造方法)
        TestThis1 hi = new TestThis1(2,3);
        hi.eat();
    }
}

程式碼示例:this 代表 “當前物件”

public class User {
    // 定義類的成員變數(類屬性)
    int id;     // id
    String name;// 賬戶名
    String pwd; // 密碼
    // 定義空構造方法
    public User(){
    }
    // 構造方法過載
    public User(int id,String name){
        // 測試呼叫方法時的 實參 到底是賦值給了誰
        System.out.println(id);    // 列印結果為 119
        System.out.println(name);  // 列印結果為 阿jun
        System.out.println(pwd);   // 列印結果為 null
        System.out.println("正在初始化已經建立好的物件(當前物件):" + this);
        // 利用 this 關鍵字將成員變數賦值給 User 構造方法的區域性變數
        this.id = id;    // 不寫 this,無法區分區域性變數 id 和 成員變數 id
        this.name = name;
    }
    // 定義普通方法
    public void login(){
        // 這裡的 this.name 等同於方法裡呼叫成員變數(屬性) name 
        System.out.println(this.name + ",要登入!");   // 不寫 this 效果一樣
    }
    // 定義 main 方法
    public static void main(String[] args) {
        // 呼叫方法時,成員變數屬性 id 和 name 都已經被分別賦值為 id=119 和 name="阿jun"
        // 呼叫方法時定義的實參是直接賦值給了外部對應的成員變數(也叫對應類屬性)
        User u3 = new User(119,"阿jun");
        // 此時列印的是 User 類中 u3 物件的記憶體地址
        System.out.println("列印的是 User 類中 u3 物件的記憶體地址:" + u3);
        u3.login();
    }
}

static 關鍵字

簡述

在類中,用 static 修飾的變數稱之為靜態變數,也稱為類變數。
類變數的宣告週期和類相同,在整個應用程式執行期間都有效。
如下特點:

  1. 類表裡是該類的公用變數,屬於類,被該類的所有例項共享,在類被載入時被顯式初始化。
  2. 對於該類的所有物件來說,static 成員變數只有一份,被該類的所有物件共享。
  3. 一般用 “類名.屬性/方法” 來呼叫。(也可以通過物件引用或類名(不需要例項化)訪問靜態成員。)
  4. 在 static 方法中,不可直接訪問非 static 的成員。

核心要點:

  • static 修飾的成員變數和方法,從屬於類。
  • 普通變數和方法從屬於物件。

程式碼示例:測試 static 關鍵字的用法

// 測試 static 關鍵字的用法
public class User2 {
    int id;
    String name;
    String pwd;
    static String company = "公眾號:阿jun修煉手冊"; // 定義靜態變數
    // 定義構造方法
    public User2(int id,String name){
        this.id = id;
        this.name = name;
    }
    // 定義普通方法
    public void login(){
        // 普通方法中呼叫靜態方法
        printCompany();
        // 普通方法中呼叫靜態變數
        System.out.println("登入名:" + company);
        // 普通方法中呼叫普通屬性
        System.out.println("登入名:" + id);
    }
    // 定義靜態方法
    public static void printCompany(){
        System.out.println(company);
        // 編譯出錯,靜態方法中無法去使用非靜態的方法/變數/常量,因為兩者在方法區中的位置不同
//        System.out.println(id);
    }
    public static void main(String[] args) {
        // 定義類物件,類物件不能去呼叫靜態方法/常量/變數
        User2 u = new User2(110, "120");
        // 通過類名去呼叫方法,列印 company 靜態變數
        User2.printCompany();
        // 靜態變數重新賦值,通過類名去呼叫 company 靜態變數
        User2.company = "阿jun 都2021年了還沒物件";
        // 通過類名去呼叫方法,列印 company 靜態變數
        User2.printCompany();
        // 物件呼叫靜態方法
        u.printCompany();
        // 物件呼叫普通方法
        u.login();
    }
}

記憶體分析圖

注意點

  1. 類載入完以後,類裡面的相關資訊(程式碼、靜態變數/常量)會載入到 方法區 中
  2. 普通的方法/變數/常量 從屬於類物件
  3. 靜態的方法/變數/常量 從屬於類。
  4. 靜態方法中無法去使用非靜態的方法/變數/常量。因為兩者在記憶體的堆中的位置不同
  5. 在普通方法中呼叫靜態的方法/屬性,沒有問題
  6. this 用於普通方法中,屬於類,不屬於物件,this 代表的是當前的物件,所以不能在靜態方法裡使用
  7. 靜態方法/變數/常量 類似於汽車的圖紙,非靜態方法/變數/常量屬類似於汽車成品。圖紙中不能找到汽車,汽車中能去找圖紙(有汽車,肯定就有圖紙,有圖紙不一定有汽車)

靜態初始化塊

簡述

構造方法用於物件的初始化。靜態初始化塊,用於類的初始化操作。
在靜態初始化塊中不能直接訪問非 static 成員。

語法格式

static {
    …………
}

使用要點

  1. 靜態塊用 static 來修飾,不給定名字。
  2. 靜態塊在類初始化的時候開始執行。
  3. 類初始化過程中,不能去呼叫非靜態的方法/變數,因為初始化過程中沒有物件。
  4. 初始化類的過程,相當於是在描繪汽車圖紙的過程。
  5. 程式在載入類的過程中,就會去將靜態塊的程式碼內容去執行。
  6. 類載入完成以後,才能構造物件。

程式碼示例:測試靜態初始化塊的使用

// 測試 靜態初始化塊
public class User3 {
    int id;
    String name;
    String pwd;
    static String company;  // 定義靜態成員變數
    // 靜態初始化塊
    static {
        System.out.println("開始進行類的靜態初始化塊,company 此時的值為:" + company);
        System.out.println("靜態初始化塊會在類載入的時候被呼叫執行。");
        System.out.println("靜態初始化塊可以去呼叫靜態的方法/變數,但不能呼叫非靜態的方法/變數(如:id、name)");
        // 呼叫靜態成員變數並賦值
        company = "公眾號-阿jun修煉手冊";
        // 呼叫靜態方法
        printCompany();
    }
    // 定義靜態方法
    public static void printCompany(){
        // 靜態方法中呼叫靜態變數
        System.out.println("被賦值以後的 company 值為:" + company);
    }
    public static void main(String[] args) {
        User3 u = null;  // 這裡並沒有建立物件,啥也沒做
    }
}

注意點

靜態初始化執行順序(學繼承以後再看,先了解)

  1. 上溯到 Object 類,先執行 Object 的靜態初始化塊,再向下執行子類的靜態初始化塊,知道我們的類靜態初始化塊為止。
  2. 構造方法執行順序與上方所述一致。
偷偷向銀河要了一把碎星✨只等你閉上眼睛撒入你的夢中。