Java基礎知識整理之this用法

Wayfreem發表於2019-01-19

具體內容

在 Java 程式中,當區域性變數全域性變數資料型別和名稱都相同的時,此時全域性變數會被隱藏而變得不能使用。即:區域性變數會覆蓋掉全域性變數

在 Java 程式中,利用 this 關鍵字可以顯示類屬性的呼叫、類方法的呼叫、表示當前物件。

使用 this 的語法格式如下:

this.成員變數名
this.成員方法名()

this 具體使用

呼叫成員變數

Demo.java

// 定義一個內部類 BookInfo
class BookInfo {
    //  內部類的屬性
    String title;
    double price;

    //  內部類的方法
    public void getInfo() {
        // 列印的結果是當前物件的屬性,是當前物件
        System.out.println("圖書名稱:" + this.title + ",價格為:" + this.price);
    }
}

public class Demo {

    public static void main(String[] args) {
        // 例項化 兩個BookInfo 的物件
        BookInfo bookA = new BookInfo();
        BookInfo bookB = new BookInfo();

        // 給 bookA 增加屬性
        bookA.price = 89.8;
        bookA.title = "Java 開發"; // 給 booA 這個物件賦值,

        // 給 bookB 增加屬性
        bookB.price = 69.8;
        bookB.title = "JSP 開發"; // 給 booB 這個物件賦值
        
        // 分別呼叫 getInfo() 方法
        bookA.getInfo();
        bookB.getInfo();
    }
}

控制檯輸出

圖書名稱:Java 開發,價格為:89.8
圖書名稱:JSP 開發,價格為:69.8

說明

通過控制檯的輸出,可以看到程式上面例項化的兩個物件:bookA、bookB,分別通過 getInfo() 列印出來的資料都是自己的,即在呼叫 BookInfo 中的 getInfo() 時,呼叫時候的 this 就是執行當時的呼叫物件。例如:當 bookA 呼叫 getInfo() 時,當前的 this 就是指的是 bookA。

成員變數的作用域

Demo.java

class BookInfo {
    String title;
    double price;

    public void getInfo() {
        String title = "我是預設值";    // 區域性變數
        
        // 輸出的結果也為區域性變數
        System.out.println("title 值為:"+ title);  
        
        // 輸出的結果為全域性變數
        System.out.println("圖書名稱:" + this.title + ",價格為:" + this.price);     
    }
}

public class Demo {

    public static void main(String[] args) {
        // 例項化 BookInfo 物件
        BookInfo bookA = new BookInfo();
        //  給  bookA 增加屬性
        bookA.price = 89.8;
        bookA.title = "Java 開發";

        bookA.getInfo();
    }
}

控制檯輸出

title 值為:我是預設值
圖書名稱:Java 開發,價格為:89.8

說明

如果我們在 BookInfo 類中的 getInfo() 方法中,全部都是使用 title,而不是使用 this.title,那麼輸出的結果就全部為 我是預設值。 那是因為我們的定義了區域性變數,如果沒有 this 關鍵字去宣告,那麼所有的 title 引入的指向都是 當前的區域性變數。在上面的程式程式碼中就是:我是預設值。

反過來看,當我們加上了 this 關鍵字,就是表示當前的物件,而 this.title 就是指的是我們定義的全域性的屬性了。

呼叫成員方法

使用傳統的方式

在使用 this 關鍵字之前,我們先看下傳統的方法。在下面的程式碼中有四個構造器方法。分別使用這四個構造器方法去建立物件。並且輸出結果。

TestDemo.java

class Emp{
    
    private int empno;
    private String ename;
    private double sal;
    private String dept;
    
    public Emp() {
        this.empno = 0;
        this.ename = "無名氏";
        this.sal = 0.0;
        this.dept = "無";
    }
    
    public Emp(int empno){
        this.empno = empno;
        this.ename = "臨時工";
        this.sal = 200;
        this.dept = "測試組";
    }
    
    public Emp(int empno, String ename){
        this.empno = empno;
        this.ename = ename;
        this.sal = 2000.0;
        this.dept = "技術部";
    }
    
    public Emp(int empno, String ename, double sal, String dept){
        this.empno = empno;
        this.ename = ename;
        this.sal = sal;
        this.dept = dept;
    }
    
    public String getInfo() {
        return "僱員編號:" + this.empno + ", 僱員名稱" + this.ename + ", 工資" + this.sal + ",部門"+ this.dept;
    }
}

public class TestDemo {
    public static void main(String[] args) {
        Emp emp1 = new Emp();
        Emp emp2 = new Emp(2);
        Emp emp3 = new Emp(3, "張三");
        Emp emp4 = new Emp(4, "張三", 5000, "經理部");
        
        System.out.println(emp1.getInfo());
        System.out.println(emp2.getInfo());
        System.out.println(emp3.getInfo());
        System.out.println(emp4.getInfo());
        
    }
}

控制檯輸出

僱員編號:0, 僱員名稱無名氏, 工資0.0,部門無
僱員編號:2, 僱員名稱臨時工, 工資200.0,部門測試組
僱員編號:3, 僱員名稱張三, 工資2000.0,部門技術部
僱員編號:4, 僱員名稱張三, 工資5000.0,部門經理部

使用 this 呼叫方法

接下來,我們使用 this 來改寫,上面的寫法肯定不是最優的方案。因為存在好多的重複性的程式碼。然後我們使用 this 來重構。但是在下面的程式碼中,需要留有一個 this 出口。
++出口是指的是:我們在建立構造器的時候,不能每一個 構造器方法中都使用 this() 方法,因為如果全部都使用,程式執行的就會陷入“遞迴呼叫” 就會報錯。++

在下面的程式碼中,我們需要了解的知識是:this() 就是指我們當前的呼叫的構造器方法。

TestDemo.java

package com.wq.study.reference;

class Emp{
    
    private int empno;
    private String ename;
    private double sal;
    private String dept;
    
    public Emp() {
        // 我們通過使用 this() 方法來呼叫我們的 四參構造方法
        this(0, "無名氏", 0.0, "無");     // 當前一行就可以替換下面的四行程式碼
        
        /*由於改寫,這段程式碼就註釋掉
        this.empno = 0;
        this.ename = "無名氏";
        this.sal = 0.0;
        this.dept = "無";*/
    }
    
    public Emp(int empno){
        this(empno, "臨時工", 200, "測試");    // 在這個地方我們也使用 this() 方法來改寫
        
        /* 由於改寫,這段程式碼就註釋掉
        this.empno = empno;
        this.ename = "臨時工";
        this.sal = 200;
        this.dept = "測試組";*/
    }
    
    public Emp(int empno, String ename){
        this(empno, ename, 2000, "技術部");    // 同樣我們使用 this() 方法來改寫
        
        /* 由於改寫,這段程式碼就註釋掉
        this.empno = empno;
        this.ename = ename;
        this.sal = 2000.0;
        this.dept = "技術部";*/
    }
    
    public Emp(int empno, String ename, double sal, String dept){
        // 我們這個地方留有出口。就不會導致產生遞迴呼叫而報錯
        this.empno = empno;
        this.ename = ename;
        this.sal = sal;
        this.dept = dept;
    }
    
    public String getInfo() {
        return "僱員編號:" + this.empno + ", 僱員名稱" + this.ename + ", 工資" + this.sal + ",部門"+ this.dept;
    }
}

public class TestDemo {
    public static void main(String[] args) {
        Emp emp1 = new Emp();
        Emp emp2 = new Emp(2);
        Emp emp3 = new Emp(3, "張三");
        Emp emp4 = new Emp(4, "張三", 5000, "經理部");
        
        System.out.println(emp1.getInfo());
        System.out.println(emp2.getInfo());
        System.out.println(emp3.getInfo());
        System.out.println(emp4.getInfo());
    }
}

控制檯輸出

僱員編號:0, 僱員名稱無名氏, 工資0.0,部門無
僱員編號:2, 僱員名稱臨時工, 工資200.0,部門測試
僱員編號:3, 僱員名稱張三, 工資2000.0,部門技術部
僱員編號:4, 僱員名稱張三, 工資5000.0,部門經理部

說明

從控制檯的輸出可以看出,這個兩個結果是沒有區別的,即說明我們改寫成功,但是需要有一點說明就是一定要在某一個 構造方法中留有出口。

this 表示當前物件

this 表示當前的物件,其實還是比較好理解。我們通過以下程式碼來了解。

Demo.java

class BookInfo {
    
    public void getInfo() {
        System.out.println("this ="+ this);
    }
}

public class Demo {

    public static void main(String[] args) {
        BookInfo bookA = new BookInfo();
        System.out.println("bookA:"+bookA);
        bookA.getInfo();
        System.out.println("--------------------");
        BookInfo bookB = new BookInfo();
        System.out.println("bookB:"+bookB);
        bookB.getInfo();
    }
}

控制檯

bookA: BookInfo@7852e922
this = BookInfo@7852e922
--------------------
bookB: BookInfo@4e25154f
this = BookInfo@4e25154f

說明

我們列印出來的訊息可以看到,this 就是當前的物件地址,指的是當前的呼叫的物件。

通過複雜的程式碼理解 this

對於 this 的理解,我們可以通過下面的複雜點的程式碼來理解。程式碼上面有詳細的註釋。大家仔細看就好了。

class A{
    private B b;    // 將 B 作為私有的成員變數
    public A() {
        this.b = new B(this);    // 2.例項化物件b,將當前的this(指的是 A)傳遞到B的構造器中, 並且將例項化出來的 B物件  給到 A 物件中的 B(為 A 物件中的私有成員變數)
        this.b.get();            // 4.通過 b 呼叫 get() 方法
    }
    
    public void print() {
        System.out.println("Hello word!");    // 6.列印輸出 Hello word!
    }
}

class B{
    private A a;    // 將 A 作為私有的成員變數
    public B(A a) {
        this.a = a;        // 3.將傳遞過來的 A 賦值給 自己的私有變數 A,由於作用域的關係,this指向的是 B
    }
    
    public void get() {
        this.a.print();        // 5.通過這個地方呼叫 A的 print()
    }
}

public class Demo {

    public static void main(String[] args) {
        A temp = new A();        // 1.例項化物件 A
    }
}

總結

  1. 類中的屬性呼叫以後都要加上 this
  2. 類中的構造方法間的互相呼叫,一定要保留有出口(即存在有一個構造方法沒有使用 this() )
  3. this 表示當前物件,指的是當前正在呼叫類中的方法的物件,this 不是一個固定的。

相關文章