具體內容
在 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
}
}
總結
- 類中的屬性呼叫以後都要加上
this
- 類中的構造方法間的互相呼叫,一定要保留有出口(即存在有一個構造方法沒有使用 this() )
-
this
表示當前物件,指的是當前正在呼叫類中的方法的物件,this
不是一個固定的。