秦学苦练: http://www.cnblogs.com/Qinstudy/
[正文]
秦学苦练博主, 你好! 我是立志要掌握 Java 编程语言的一名小白, 最近我在学习 Java 中的面向对象的三大特性 (封装, 继承, 多态) 时, 常常会碰到 this 关键词, 但书上只是简单讲了 this 的几个作用, 我听得是云里雾里, 并没有讲解 Java 设计者为什么要创建 this 关键字, 是出于一个什么原因创建了 this 关键字呢? 还有 this 关键字解决了什么问题呢?
这些都是我的疑惑, 至于我为什么问到这些问题, 是因为我觉得学习概念不仅仅要学习概念的本身, 更重要的是了解, 理解知识的由来. 再次拜谢博主啦 ---- 秦学苦练
秦学苦练的回答:
小张, 你好! 我刚开始学习 this 时, 也只知道 this 关键字在程序中有哪些作用, 但不知道 this 关键字怎么产生的? 你讲的这句话很好 -- 学习概念不仅仅要学习概念的本身, 更重要的是了解, 理解知识的由来.
你提出了两个问题, 我把问题罗列出来:
1.Java 设计者为什么要创建 this 关键字, 是出于一个什么原因创建了 this 关键字呢? 简言之, this 关键字产生的背景
2. 还有 this 关键字解决了什么问题呢? 简言之, this 关键字的作用
受 "更重要的是了解, 理解知识的由来" 的鼓舞, 我去网上查阅了相关资料,Java 编程思想(第四版第 5 章 5.4,P84 页)给出了不错的回答. 下面我把书中的知识按照自己的理解讲述一下:
this 关键字可以这么去理解, 在英语中, 指示代词 this, 用来指代某个东西, 例如: Look,this is a table. this 指代 table.
在 Java 语言的设计中, this 也是具有指向关系的.
1. this 关键字产生的背景
我先来回答, Java 设计人员为什么创建了 this 关键字? 我将用一段代码来说明原因.
- class Person{
- public void speak(){
- System.out.println("某一个对象去调用方法");
- }
- public static void main(String[] args){
- Person p1=new Person();
- Person p2=new Person();
- p1.speak(); //p1 对象去调用 speak()方法
- p2.speak(); //p2 对象去调用 speak()方法
- }
(亲测)运行结果:
某一个对象去调用方法
某一个对象去调用方法
但是, 当只有一个 speak()方法, 编译器如何知道 speak()方法是被 p1 还是被 p2 所调用的呢? 为了能用简便, 面向对象的语法来编写代码 -- 即 "发送消息给对象", 编译器做了一些幕后工作. 它暗自把 "所操作对象的引用" 作为第一个参数传递给 speak()方法. 所以上述调用后的方法变成了这样:
- Person speak(p1);
- Person speak(p2);
这是内部的表现形式. 如果我们这样写, 编译器会报错, 但这种写法会帮助你去理解编译器所做的事. 假设你希望在方法的内部获得对当前对象的引用, 由于这个引用是编译器 "偷偷" 传入的, 所以没有标识符可用.
于是, 为了解决'在方法的内部获得对当前对象的引用'这一背景问题, Java 设计师专门设计了 this 关键字, 用来在方法的内部获得对当前对象的引用. this 关键字只能在方法内部使用, 表示对 "调用方法的那个对象" 的引用. 可以这么说, this 的用法和其他 new 出来对象的引用并无不同.
但要注意, 如果在方法内部调用同一个类的另一个方法时, 可以省略 this, 直接调用即可. 因为当前方法中的 this 引用会自动应用于同一类中的其他方法. 所以小张你可以这样写代码, 编译器是不会报错的:
- class Person{
- public void speak(){}
- public void eat(){
- // 在方法内部调用同一个类的另一个方法时, 可以省略 this, 直接调用即可.
- speak(); // 编译器自动翻译成 this.speak().
- }
- public static void main(String[] args){
- }
- }
这就是 this 关键字为什么产生了, 小张啊, 总而言之, this 关键字产生的背景: 为了解决'在方法的内部获得对当前对象的引用'这一问题. this 关键字被设计出来了, 用来在方法的内部获得对当前对象的引用.
2.this 关键字的作用
三大作用:
1) 区分局部变量和成员变量同名情况, this. 成员变量调用本类中的成员变量;
2)通过 this. 方法 () 调用本类中的方法;
3)this 在构造方法之间的调用.
小张啊, 也许你看了这三大作用, 可能还是云里雾里. 你在信中, 说自己在学习 Java 中的面向对象的三大特性(封装, 继承, 多态), 所以我认为你已经懂了 private 封装, extends 继承, 并且
知道 set,get 方法, 和空参, 有参构造方法的相关概念. 下面这个程序需要你有上面的这些基础, 如果你暂时没有这些基础, 不用着急, 先去看看这些基础. 看懂这些基础后, 你再回过头来, 看下面的代码, 你会有种豁然开朗的顿悟!
如果你已经有了上面这些基础, 下面我用一个完整的程序将 this 关键字的三大作用讲清楚.
- package day_12;
- //Person 类
- public class Person {
- private String name;
- private int age;
- public Person(String name){//String name 中的 name 是局部变量
- // this 的作用 1: 区分局部变量和成员变量同名情况
- this.name=name; //this.name 中的 name 是成员变量
- }
- public Person(String name,int age){
- // 作用 3:this 关键字在构造方法间的调用
- this(name); // 用 this(name)去调用只有一个参数 name 的构造方法
- this.age=age;
- }
- public void setName(String name){
- this.name=name;
- }
- public String getName(){
- return this.name;
- }
- public void setAge(){
- this.age=age;
- }
- public int getAge(){
- return this.age;
- }
- }
- package day_12;
- //Worker 类
- public class Worker extends Person {
- public Worker(String name,int age){
- super(name,age); //super(name,age) 调用父类 Person 的具有两个参数的构造方法.
- }
- public void work(){
- // 作用 2:this 在方法中的使用
- System.out.println(this.getName()+"在砍树!");
- }
- }
使用 this.getName() 有封装的思想在里面. 由于不知道调用 getName()方法的对象是谁, 我就用模糊的概念, 哪个对象去调用 work()方法, this 就指代哪个对象.
很显然, Worker 类的对象 wk 去调用 work()方法, 那 this 就指向了 wk 对象. 所以用 this.getName()来获得 wk 对象中的属性: 光头强.
- // 测试类: Test
- package day_12;
- public class Test {
- public static void main(String[] args){
- Worker wk=new Worker("光头强",28);
- wk.work();
- }
- }
(亲测)运行结果: 光头强在砍树!
3. 方法论
小张, 很高兴, 你能提出这样两个问题, 这两个问题促使我去思考 this 关键字产生的背景以及 this 的三大作用. 给你讲述了 this 之后, 我觉得自己对 this 的理解又加深了! 小张啊, 以后在 Java 学习过程中遇到云里雾里的问题, 尽管给我写信, 只要是我能弄明白的, 一定平铺直叙地讲清楚. 学习一门语言, 多思考, 常总结是不错的状态, 与你共勉!
来源: https://www.cnblogs.com/Qinstudy/p/Qinstudy.html