The this keyword(this关键字)
If you have two objects of the same type called a and b, you might wonder how it is that you can call a method peel( ) for both those objects:
如果有同一个类型的两个对象a和b,你可能想知道如何a和b对象都能调用peel这个方法:
//: initialization/BananaPeel.java
class Banana { void peel(int i) { /* ... */ } }
public class BananaPeel {
public static void main(String[] args) {
Banana a = new Banana(),
b = new Banana();
a.peel(1);
b.peel(2);
}
}
If there’s only one method called peel( ), how can that method know whether it’s being called for the object a or b?
如果只有一个peel(),它如何知道是a还是b调用的呢?
To allow you to write the code in a convenient object-oriented syntax in which you “send a message to an object,” the compiler does some undercover work for you. There’s a secret first argument passed to the method peel( ), and that argument is the reference to the object that’s being manipulated. So the two method calls become something like:
为了能用简便、面向对象的语法编写代码,即使用"发送消息给对象",编译器在幕后做了一些工作。 它暗自把"所操作对象的引用"作为第一个参数传递给peel()。 所以上述的两个方法的调用变成这样:
Banana.peel(a, 1);
Banana.peel(b, 2);
This is internal and you can’t write these expressions and get the compiler to accept them, but it gives you an idea of what’s happening.
这是内部表示形式,并不能这样书写代码,并且试图编译通过,但这种写法的确帮助我们理解实际发生的事情。
Suppose you’re inside a method and you’d like to get the reference to the current object. Since that reference is passed secretly by the compiler, there’s no identifier for it. However, for this purpose there’s a keyword: this. The this keyword—which can be used only inside a non-static method —produces the reference to the object that the method has been called for. You can treat the reference just like any other object reference. Keep in mind that if you’re calling a method of your class from within another method of your class, you don’t need to use this. You simply call the method. The current this reference is automatically used for the other method. Thus you can say:
//: initialization/Apricot.java
public class Apricot {
void pick() { /* ... */ }
void pit() { pick(); /* ... */ }
}
Inside pit( ), you could say this.pick( ) but there’s no need to. 1 The compiler does it for you automatically. The this keyword is used only for those special cases in which you need to explicitly use the reference to the current object. For example, it’s often used in return statements when you want to return the reference to the current object:
1 Some people will obsessively put this in front of every method call and field reference, arguing that it makes it “clearer and more explicit.” Don’t do it. There’s a reason that we use high-level languages: They do things for us. If you put this in when it’s not necessary, you will confuse and annoy everyone who reads your code, since all the rest of the code they’ve read won’t use this everywhere. People expect this to be used only when it is necessary. Following a consistent and straightforward coding style saves time and money.
//: initialization/Leaf.java
// Simple use of the "this" keyword.
public class Leaf {
int i = 0;
Leaf increment() {
i++;
return this;
}
void print() {
System.out.println("i = " + i);
}
public static void main(String[] args) {
Leaf x = new Leaf();
x.increment().increment().increment().print();
}
}
/* Output:
i = 3
*///:~
Because increment( ) returns the reference to the current object via the this keyword (通过this关键字返回当前对象的引用), multiple operations can easily be performed on the same object.
The this keyword is also useful for passing the current object to another method:
this关键字对于将当前对象传递给其他方法也很有用:
//: initialization/PassingThis.java
package com.test;
@SuppressWarnings("unused")
class Person1 {
public void eat(Apple apple) {
Apple peeled = apple.getPeeled();
System.out.println("Yummy");
}
}
class Peeler {
static Apple peel(Apple apple) {
// ... remove peel
return apple; // Peeled
}
}
class Apple {
Apple getPeeled() {
return Peeler.peel(this);
}
}
/**
* 程序传递当前对象
* 调用顺序:首先调用Person1的eat方法,当前对象为Person1的对象。
* 接着当前对象为apple,调用Apple的getPeeled方法,最终返回一个apple对象的引用。
* @author 守望幸福
*
*/
public class PassingThis {
public static void main(String[] args) {
new Person1().eat(new Apple());//调用eat方法
}
}
/* Output:
Yummy
*///:~
Apple needs to call Peeler.peel( ), which is a foreign utility method that performs an operation that, for some reason, needs to be external to Apple (perhaps the external method can be applied across many different classes, and you don’t want to repeat the code). To pass itself to the foreign method, it must use this.
package com.test;
/**
* first第二个调用second方法实际编写时不需要添加this,编译器会自动添加
* @author 守望幸福
*
*/
public class ThisExcise {
void first(){
second();
this.second();
System.out.println(this.getClass());//class com.test.ThisExcise
}
void second(){
System.out.println("I had called!");
}
public static void main(String[] args) {
new ThisExcise().first();
}
}
//返回当前对象的引用
package com.test;
/**
* this关键字只能在非static方法内使用,表示对"调用方法的那个对象"的引用。
* increment方法的调用为tk,因此retrun this;表示返回tk对象的引用。
* 调用之后的类型为ThisKeyword
* @author 守望幸福
*
*/
public class ThisKeyword {
int i=0;
ThisKeyword increment(){
i++;
return this;
}
void print(){
System.out.println("i="+i);
}
public static void main(String[] args) {
ThisKeyword tk=new ThisKeyword();
System.out.println(tk.increment().getClass());//class com.test.ThisKeyword i=1
System.out.println(tk.increment().increment().getClass());//class com.test.ThisKeyword i=3
tk.increment().increment().print();//i=5
}
}