深入理解this關鍵字
Java中的this關鍵字總是指向呼叫該方法的物件。
- 在構造器中,引用該構造器正在初始化的物件
- 在方法中,引用呼叫該方法的物件
package com.ch05; public class Dog { public void jump(){ System.out.println("正在執行jump方法"); } public void run(){ Dog d = new Dog(); d.jump(); // this.jump(); 或者 jump(); System.out.println("正在執行run方法"); } }
package com.ch05;
public class DogTest {
public static void main(String[] args) {
Dog dog = new Dog();
dog.run();
}
}
在上面的程式中,一共產生了兩個Dog物件,在Dog類的run()方法中,程式建立了一個Dog物件,並使用名為d的引用變數來指向該Dog物件;在DogTest的main()方法中,程式再次建立了一個Dog物件,並使用名為dog的引用變數來指向該Dog物件。
這裡產生了兩個問題。第一個問題:在run()方法中呼叫jump()方法時是否一定需要一個Dog物件?第二個問題:是否一定需要重新建立一個Dog物件?第一個問題的答案是肯定的,因為沒有使用static修飾的成員變數和方法都必須使用物件來呼叫。第二個問題的答案是否定的,因為當程式呼叫run()方法時,一定會提供一個Dog物件,這樣就可以直接使用這個已經存在的Dog物件,而無須重新建立新的Dog物件了。
this可以代表任何物件,當this出現在某個方法體中時,它所代表的物件是不確定的,但它的型別是確定的:它所代表的只能是當前類的例項;只有當這個方法被呼叫時,它所代表的物件才被確定下來:誰在呼叫這個方法,this就代表誰。
對於static修飾的方法而言,則可以使用類來直接呼叫該方法,如果在static修飾的方法中使用this關鍵字,則這個關鍵字就無法指向合適的物件。所以,static修飾的方法中不能使用this引用。由於static修飾的方法不能使用this引用,所以static修飾的方法不能訪問不使用static修飾的普通成員,因此Java語法規定:靜態成員不能直接訪問非靜態成員。
package com.ch05; public class StaticAccessNonStatic { public void info(){ System.out.println("Hello"); } public static void main(String[] args){ // 因為main()方法是靜態方法,而info()是非靜態方法 // 呼叫main()方法的是該類本身,而不是該類的物件 // 因此省略的this無法指向有效的物件 info(); } }
編譯上面程式出現如下錯誤: java: 無法從靜態上下文中引用非靜態 方法 info()
Java程式設計時不要使用物件去呼叫static修飾的成員變數、方法,而是應該使用類去呼叫static修飾的成員變數、方法!如果確實需要在靜態方法中訪問另一個普通方法,則只能重新建立一個物件。例如,將上面的info()呼叫改為:new StaticAccessNonStatic().info()
;
this的其他作用
package com.ch05;
public class ThisInConstructor {
public int foo;
public ThisInConstructor(){
// 下面的區域性變數與成員變數同名
int foo = 0;
this.foo = 6;
}
public static void main(String[] args) {
System.out.println(new ThisInConstructor().foo); // 6
}
}
大部分時候,在構造器中訪問其他成員變數和方法時都可以省略this字首,但如果構造器中有一個與成員變數同名的區域性變數,又必須在構造器中訪問這個被覆蓋的成員變數,則必須使用this字首。
package com.ch05;
public class ReturnThis {
public int age;
public ReturnThis grow(){
age++;
return this;
}
public static void main(String[] args) {
ReturnThis returnThis = new ReturnThis();
returnThis.grow()
.grow()
.grow();
System.out.println(returnThis.age);
}
}
如果在某個方法中把this作為返回值,則可以多次連續呼叫同一個方法,從而使得程式碼更加簡潔。