先来看看这段代码
public class Person {
String name; //属性
Person(String name) { //有参构造方法
name = name; // 1 //将参数的name赋值给类的属性name
}
void says(String content) { //方法
System.out.println(name + ":" + content); // 2 输出属性name字符串":"和参数
}
public static void main(String[] args) { //main函数
Person p1 = new Person("Tom"); //实例化对象p1
p1.says("byebye"); //引用方法says
Person p2 = new Person("God"); //实例化对象p2
p2.says("goodluck"); //p2调用方法says
}
}
运行这个程序,会输出“Tom:byebye”吗?
我们看一下运行结果
答案当然是否定的,问题出在标记为 1 的位置。“name=name”,在此的两个 name 其实均为参数中的 name,并没有给类的属性 name 赋值,所以程序中的 name 其实一直为 null.为解决这个问题,我们只需要将标记 1 的代码改为“this.name = name”即可。
代码如下图:
public class Person {
String name; //属性
Person(String name) { //有参构造方法
this.name = name; // 1 //将参数的name赋值给类的属性name
}
void says(String content) { //方法
System.out.println(name + ":" + content); // 2 输出属性name字符串":"和参数
}
public static void main(String[] args) { //main函数
Person p1 = new Person("Tom"); //实例化对象p1
p1.says("byebye"); //引用方法says
Person p2 = new Person("God"); //实例化对象p2
p2.says("goodluck"); //p2调用方法says
}
}
运行结果如下:
那么 this 是什么呢?
this 关键字的含义:可以为调用了其方法的对象生成相应句柄。也就是说,哪个对象
调用了方法,这个方法内的 this 指的就是哪个对象。(指定当前对象)
可能大家还有疑惑,那么我们来想一想,对于程序中的pl、p2 对象,它们均调用了says()方法,但编译器是怎样知道你要调用哪个对象的says0方法呢?其实,为了能用简便的、面向对象的语法来书写代码,即“将消息发给对象”,编译器为我们完成了一些幕后工作,其中的秘密就是将准备操作的对象的引用传递给方法says()。所以前述的两个方法调用就变成下面的形式。
Test.says(pl,"byebye"); //对应 pl.says()
Test.says(p2,"goodluck"); //对应 p2.says()
//这是计算机内部表达形式,不能这样书写
这是内部的表达形式,我们并不能这样书写表达式,并试图让编译器接受它。
但是,通过它可理解幕后到底发生了什么事情。这样一来,当执行pl.says0时,其中的name指的就是p1.name; 执行p2.says时,其中的name指的就是p2.name。由此可以推测,says()方法中的name的完整写法就是“this.name”。为说明这个问题,我们把标记 2 处的name改为“this.name”,重新运行程序将发现,与改前没有任何区别。