1. this是指当前对象自己。
当在一个类中要明确指出使用对象自己的的变量或函数时就应该加上this引用。如下面这个例子中:
public
class A {
String s = "Hello";
public A(String s) {
System.out.println("s = " + s);
System.out.println("1 -> this.s = " + this.s);
this.s = s;
System.out.println("2 -> this.s = " + this.s);
}
public static void main(String[] args) {
new A("HelloWorld!");
}
}
运行结果:
s =
HelloWorld!
1 -> this.s = Hello
2 -> this.s = HelloWorld!
在这个例子中,构造函数A中,参数s与类A的变量s同名,这时如果直接对s进行操作则是对参数s进行操作。若要对类A的变量s进行操作就应该用this进行引用。运行结果的第一行就是直接对参数s进行打印结果;后面两行分别是对对象A的变量s进行操作前后的打印结果。
2.
把this作为参数传递
当你要把自己作为参数传递给别的对象时,也可以用this。如:
public
class A {
public A() {
new B(this).print();
}
public void print() {
System.out.println("Hello from A!");
}
}
public class B {
A a;
public B(A a) {
this.a = a;
}
public void print() {
a.print();
System.out.println("Hello from B!");
}
}运行结果:
Hello
from A!
Hello from B!
在这个例子中,对象A的构造函数中,用new B(this)把对象A自己作为参数传递给了对象B的构造函数。
3.
注意匿名类和内部类中的中的this。
有时候,我们会用到一些内部类和匿名类。当在匿名类中用this时,这个this则指的是匿名类或内部类本身。这时如果我们要使用外部类的方法和变量的话,则应该加上外部类的类名。如下面这个例子:
public
class A {
int i = 1;
public A() {
Thread thread = new Thread() {
public void run() {
for(;;) {
A.this.run();
try {
sleep(1000);
} catch(InterruptedException ie) {
}
}
}
};
thread.start();
}
public void run() {
System.out.println("i = " + i);
i++;
}
public static void main(String[] args) throws Exception {
new A();
}
}在 上面这个例子中, thread 是一个匿名类对象,在它的定义中,它的 run 函数里用到了外部类的
run 函数。这时由于函数同名,直接调用就不 行了。这时有两种办法,一种就是把外部的 run
函数换一个名字,但这种办法对于一个开发到中途的应用来说是不可取的。那么就可以用这个例子中的办法用 外部类的类名加上 this
引用来说明要调用的是外部类的方法 run。
转自:http://www.openitpower.com/wenzhang/208/34211_1.html
以下摘自《Thinking
in java 4th》
this关键字
假如你有两个同类型的称为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);
}
} ///:~
如果类定义里仅有一个叫做peel()的方法,这个方法怎么知道它为对象a还是b调用的呢?
为了让你使用方便的面向对象的语法编写代码,让你只管为对象发送消息,编译器在暗地里为你做了一些工作。
编译器把正在调用的对象的引用当作第一个秘密参数传递给方法peel()。 因此两个peel()方法的调用变成了这样:
Banana.peel(a,1); Banana.peel(b, 2);
这是编译器内部处理方式,你不可以编写像上面这样的代码,编译器也不会接受它们,但是上面的代码却告诉你发生了什么。
设想你正在一个方法里编写代码,你想得到当前对象的引用。 既然a和b对象引用是被编译器暗地里发送的,那么就没法识别这些暗地里使用的引用。
不过,为了得到对当前对象的引用,java编程语言中存在一个关键字: this。
this关键字——只能在非static方法里
使用——生成方法所需要的对象引用。 你可以像看待其它对象引用一样看待this。
记住,如果在你的类里,你正在一个方法里调用同一个类里的另一个方法,就没有必要使用this。 简单地调用那个方法就是了。
this引用会被自动地使用在那个方法的调用语句中。 因此你可以这样写:
//: initialization/Apricot.java
public class Apricot {
void pick() { }
void pit() { pick(); }
} ///:~
在pit()方法里,你可以写this.pick(),但是没有必要1。编译器会替你自动加上this。
this关键字只在你需要明确使用当前对象引用的特殊情况下派上用场。
举个例子,当你想返回当前对象的引用时,this就经常在return语句中使用。
//: 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();
}
} //:~
因为increment()通过this关键字返回了当前对象的引用,所以同一个对象的多次操作能够容易执行。
1 一些人会强迫性地将this写在每一个方法和field引用的前面,并辩解说这样写使代码更加清楚和明确。 别这样做。
我们使用高级编程语言的一个理由就是: 高级编程语言替我们做了一些事情。
如果你在没有必要的情况下使用this,你会迷惑和惹恼每一个阅读你代码的人,因为他们读的别的代码不会在每个地方都使用this。
人们期待this在必要的时候才被使用。 遵守一致和简明的代码风格会为你节省时间和金钱。
this关键字也可用于将当前对象传递给另一个类的某个方法:
//: initialization/PassingThis.java
class Person {
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); } }
public class PassingThis {
public static void main(String[] args) { new Person().eat(new
Apple());
}
} //:~
Apple需要调用Peeler.peel(),peel()是一个外部实用方法,由于某种原因它有必要是不属于Apple类的外部方法(或许很多不同的类都要完成这个外部方法所执行的任务,而你又不想重复写那些代码。
传递对象自身给外部方法,相应的类必须使用this。
练习8: (1)创建一个定义了两个方法的类。 在第一个方法内部,调用第二个方法两次:
第一次不使用this,第二次使用this——仅为了明白这样写代码它也是可以工作地;你不应该在实践中使用这种形式。
从constructors中调用constructors
当你为某个类写了好几个constructors
时,有时候为了避免重复代码你愿意从一个constructor内调用另一个constructor。
使用this关键字你能够实现这样的调用。
正常情况下,当提到this时,它的意思是“这个对象”或者“当前对象,”通过它自己this生成了对当前对象的引用。
但是在constructor内部,当你为this关键字输入参数组时,this的意思会有所不同。
这时this明确调用了参数组匹配的constructor。 因此你有了调用别的constructors的简明方式。
//: initialization/Flower.java
// Calling constructors with "this"
import static net.mindview.util.Print.*;
public class Flower {
int petalCount = 0;
String s = "initial value";
Flower(int petals) {
petalCount = petals;
print("Constructor w/ int arg only, petalCount= "
+ petalCount);
}
Flower(String ss) {
print("Constructor w/ String arg only, s = " + ss);
s = ss;
}
Flower(String s, int petals) {
this(petals);
//! this(s); // Can't call two!
this.s = s; // Another use of "this"
print("String & int args");
}
Flower() {
this("hi", 47);
print("default constructor (no args)");
}
void printPetalCount() {
//! this(11); // Not inside non-constructor!
print("petalCount = " + petalCount + " s = "+ s);
}
public static void main(String[] args) {
Flower x = new Flower();
x.printPetalCount();
}
} //:~
constructor Flower(String s,int
petals)表明当你使用this调用某个constructor的时候,你不可以使用两次this。
另外,在某个constructor内部调用另一个constructor必须是你要做的第一件事情,你不这样做就会得到一个编译错误消息。
等一下你就会明白这个例子也说明了this的另一个用途。 因为参数的名字s和member data的名字s相同,存在歧义的情况。
你可以使用this.s解决这个问题,意思是说你在引用member data。
在Java代码里你会经常看到这种形式的应用,本书中也大量使用了。
在printPetalCount()里,你能明白除了constructor编译器不会让你在任何方法内部调用constructor。