![名师讲坛:Java开发实战经典(第2版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/824/26793824/b_26793824.jpg)
5.9 this关键字
在Java中this关键字可能是读者最难理解的了,因为其语法较为灵活,this到底有哪些用处呢?从之前的代码中读者应该已经发现,可以使用this强调本类中的方法,除此之外this还有以下作用:
(1)表示类中的属性。
(2)可以使用this调用本类的构造方法。
(3)this表示当前对象。
5.9.1 使用this调用本类中的属性
在程序中可以使用this调用本类属性。
【例5.43】现在有以下的一个类
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P125_124143.jpg?sign=1739266180-I7KsCtfBSM7AGqL4LoCgalR6WyVSN9EZ-0-58b29843953149192a4625a0d4ec52f7)
在本类中构造方法的目的很明确,就是为类中的属性赋值,但是从构造方法传递的两个参数名称上是很难看出“n表示的意义”或是“a表示的意义”,为了可以清楚地表示参数的意义,将以上的类修改为如下的形式:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P126_124145.jpg?sign=1739266180-PlmTH8EILTOuTdZKTis31FoAgaAZVfGa-0-6a63e9980480823bc6af156b3b6acbed)
此时,从参数的名称上可以很清楚地知道,要传递的第一个参数是姓名,第二个参数是年龄,但是这样一来,又一个新的问题出现了:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P126_124146.jpg?sign=1739266180-klz4ZEay9fQU4dO07E2XhzdyeikQlD1T-0-a85af061645eabf49b47a50a3b965135)
类的本意是要将参数传递的name值赋给类中的name属性,把age的值赋给age属性,但是以上程序真的可以达到这样的效果吗?下面来验证一下:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P126_124147.jpg?sign=1739266180-coXTdsvZDWpM4jZPNKP5osY7uQRASsDI-0-e74612140d16c9b5f545c22ee21a984e)
程序执行结果:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P127_124148.jpg?sign=1739266180-wt2g30snhtauhVocKKDz7qAdE1gv7eqy-0-9d35c459cce8b7cb154a310f54393929)
从结果中可以发现,姓名为“null”,年龄为“0”,也就是说并没有把从构造方法中传递进去的参数值赋给属性,现在的构造方法并不能成功地把传递进去的值赋值给类中的属性。可见,在赋值的时候属性并不是明确地被指出,所以造成错误,而这种错误可以利用this关键字来解决,代码修改如下:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P127_124149.jpg?sign=1739266180-FKAe6T1QkTCVsw3R2guMFYklDSx0cGNr-0-2088b43d630ba6612dd2ed0a8f794df1)
程序执行结果:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P127_124150.jpg?sign=1739266180-GJHwVQVxkX9JWppBeC4WBURSpLLOMwfK-0-7b9ceebdc6176ee03e609bdb5d826c63)
从程序运行结果来看,达到了所需要的目的,而在构造方法之中,因为已经明确地标识出了类中的两个属性:“this.name”和“this.age”,所以在进行赋值操作的时候也不会产生歧义。
说明
提问:之前的代码操作的是哪个属性?
对于上面代码很容易的知道哪个是属性,哪个是参数,但是之前的代码呢:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P127_124154.jpg?sign=1739266180-vPx5Qfe1ZCZcY1qarkp9srBxpay4ShFc-0-97f37ce51e6eebf0c39f19026b60099f)
这里的name和age分别是什么呢?
回答:都是方法中的参数。
实际上以上的“name=name”“age=age”的代码中的两个name和两个age都是构造方法中的参数,这是为什么呢?举例来说:
假设现在一个用户要拿笔写字,摆在此用户面前的有一支笔,离用户10米远的地方还有一支笔,那么如果你是这个用户,你会选择哪支笔?没错,肯定会使用身边的这支笔,因为离得近。
实际上对于程序上也是一样的,在程序的构造方法中已经存在了name和age属性,那么在构造方法中如果要使用name或age属性的话,则肯定要找近的,所以以上的name和age使用的都是构造方法中的参数。
所以,为了方便,建议读者以后在类中访问属性的时候都要加上this关键字。
5.9.2 使用this调用构造方法
如果一个类中有多个构造方法的话,也可以利用this关键字互相调用。
假设现在要求不管类中有多少个构造方法,只要对象一被实例化,就必须打印一行“一个新的Person对象被实例化”的信息出来,很明显,此时如果在各个构造方法中编写此输出语句肯定不合适,所以此时就可以利用this的概念完成。如下面代码。
【例5.44】使用this调用本类的构造方法
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P128_124155.jpg?sign=1739266180-jQNQXNUuNKpU8CNeIJhyib2HSfija7te-0-bd41b1f80043f53350af60af5e1646ad)
程序执行结果:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P128_124156.jpg?sign=1739266180-HfTjaJL4vzhtkqqcSlVeQlUBhy3vhDiJ-0-7e1f5c4e2ecf3af25128b30e0dea4017)
本程序中提供了两个构造方法,其中有两个参数的构造方法中使用“this()”的形式调用了本类中的无参构造方法,所以即使是通过有两个参数的构造方法实例化,最终结果还是会把对象实例化的信息打印出来。
如果把this()调用无参构造方法的位置任意调换,在任何时候都可以调用构造方法了吗?实际上这样理解是错误的。构造方法是在实例化一对象时被自动调用的,也就是说在类中的所有方法里,只有构造方法是被优先调用的,所以使用this调用构造方法必须也只能放在构造方法的第一行,下面的程序就是一个错误的程序。
【例5.45】错误的代码调用
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P128_124157.jpg?sign=1739266180-UvHfKV17kuAqfYzfXPnMNqQy7N1WwX9t-0-3113ec82acaec2300f415ed53ab4a6e2)
程序编译时出错:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P129_124159.jpg?sign=1739266180-ghvbV8D7XTvYe0klyd4SjBGO79NKw9p7-0-4af9b5aa421f2411334787abded5db99)
以上的错误提示就是this()只能放在构造方法的首行。
另外,对于this调用构造方法的时候一定要留一个构造方法作为出口,即程序中至少存在一个构造方法是不使用this调用其他构造方法的。
【例5.46】错误的代码
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P129_124160.jpg?sign=1739266180-vYMt2RJ2jQ9CbMMV2jh0w15Z9UzO7Fxi-0-9b28484cc84913de35c067b6c09548c7)
程序编译时出错:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P129_124161.jpg?sign=1739266180-QVk0ivcjjuHRakSCa4qb39uH48FVbXOp-0-79154a773d7b77bbc23599339b3bb6a0)
以上的错误提示为递归调用了构造方法,所以在构造方法间互相调用的时候一定要留一个出口,一般都将无参构造方法作为出口,即在无参构造方法中最好不要再去调用其他构造方法。
5.9.3 this表示当前对象
以上已经为读者讲解了何时使用this调用属性,何时使用this调用方法,实际上在这些特性之外,this最重要的特点就是表示当前对象,在Java中当前对象就是指当前正在调用类中方法的对象。
提示
关于当前对象的解释。
现在假设有张三、李四、王五3个人在谈话,如果现在说话的人是张三,则“当前正在说话的人”就是张三;如果现在说话的人是李四,则“当前正在说话的人”就是李四;依此类推,所以只要是“当前正在说话的人”,那么就表示是当前对象。
【例5.47】观察this表示当前对象
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P130_124164.jpg?sign=1739266180-Yt3bAuLL3GpEp33FO7LeMnhVqnBNgmog-0-cfab239f74eb4656038dd9d75e8a7a7d)
程序执行结果:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P130_124165.jpg?sign=1739266180-drRQbfl2ApqgmsdnFkrc65a4wiVprVkV-0-891e4e9642833bc953e0a2702dd200f3)
从程序的运行结果来看,直接打印对象和调用getInfo()方法打印的结果是一样的,而且在getInfo()方法中永远是一个this关键字,也就是说那个对象调用了类中的方法,则this就表示那个对象。那么这样的一个特性到底有什么用处呢?下面通过一个实例,来分析this表示当前对象的用法。
现在假设有以下的类:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P130_124166.jpg?sign=1739266180-i3ONGfBkqFyoXqClfFnXNHl8JXuJRivh-0-a782f6a14907f2e6985a55833eddc77f)
在此类中有name和age两个属性,现在要求产生两个Person对象,并且判断这两个对象是否相等。那么这个时候就会产生以下两个问题。
(1)如何进行对象的比较?
(2)在哪里进行对象的比较?
对于第1个问题实际上从之前讲解String的代码中读者就应该可以了解到,要想进行对象的比较,是必须比较其内容才可以,但是Person中现在并不能使用equals()方法,所以此时就需要对每一个属性进行依次的判断,如果所有属性的内容都相等了,那么就可以证明这两个对象相等,这一点可以通过如下的代码进行验证。
【例5.48】对象比较的第1种方式
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P131_124168.jpg?sign=1739266180-I1QHUVvaJvOxZXkA1XTXvzguVGkJYmnA-0-7d8782ef0c435d06e42b21aceb41da0d)
程序执行结果:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P131_124169.jpg?sign=1739266180-XelMFWWdktQuZ2VZ7Zh685vukQsoSPZM-0-295cc641523622e591f2f487480540ec)
以上的程序确实完成了两个对象的比较功能,但是一个新的问题又来了,把所有的判断方法放在主方法中合适吗?实际上这也就是之前所提出的第2个问题:“在哪里进行对象的比较?”,读者可以做这样的一个比喻,假如现在有两个人,如果一个人要判断另外一个人和自己是否相等,则肯定由这个人发出比较的请求,即在人这个类中就应该存在与其他人比较的方法。所以,对象比较的方法应该放在Person类之中,而不应该在main()方法中进行编写,修改后的代码如下。
【例5.49】修改后的对象比较操作
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P132_124170.jpg?sign=1739266180-qzFhmeGYhMyCCFBcVB9EnHHpAiQ2Lpnm-0-0ef9f4c26110b685634c1bb4fa6ece31)
程序执行结果:
![](https://epubservercos.yuewen.com/DE8B7B/15253389304122106/epubprivate/OEBPS/Images/Figure-P133_124172.jpg?sign=1739266180-wTj7Op2tyHM2QKMMm0MiBJLDblI3vyZH-0-b04b9a588a529946c9ce9daad3ccce7c)
以上程序Person类中定义了一个compare()方法,此方法的主要功能就是专门完成两个对象的比较操作,在比较时,首先进行地址的比较,如果两个对象的地址一样,则肯定是同一个对象,而如果地址不相等,则将一个个属性进行依次的比较。
注意
对象比较操作。
对象比较操作在开发中是一个重要的概念,在随后的章节部分还将进行介绍,但其基本的操作形式是不变的,所以一定要重点掌握。