1. 程式人生 > >Java基礎知識回顧之this關鍵字

Java基礎知識回顧之this關鍵字

相關關鍵字的說明:
this關鍵字
final關鍵字
static關鍵字修飾屬性
static關鍵字修飾方法
static關鍵字應用與總結

具體內容

在 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: [email protected]
this = [email protected]
--------------------
bookB: [email protected]
this = [email protected]

說明

我們打印出來的訊息可以看到,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 不是一個固定的。