类本身的方法调用类的其他方法
![](https://img-blog.csdnimg.cn/cb2cd5cd148a45268f11d4bb2fa045c5.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBATWFyc19wcmltZQ==,size_20,color_FFFFFF,t_70,g_se,x_16)
➢
构造器中引用该构造器正在初始化的对象。
➢
在方法中引用调用该方法的对象。
this关键字最大的作用就是让类中一个方法,访问该类里的另一个方法或实例变量。假设定义了一个Dog类,这个Dog对象的run()方法
需要调用它的jump()方法,那么应该如何做?是否应该定义如下的Dog
类呢?
![](https://img-blog.csdnimg.cn/7ca9f1ae9f9341ac97b23e3632ddb54b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBATWFyc19wcmltZQ==,size_20,color_FFFFFF,t_70,g_se,x_16)
使用这种方式来定义这个Dog类,确实可以实现在run()方法中调用jump()方法。那么这种做法是否够好呢?下面再提供一个程序来创
建Dog对象,并调用该对象的run()方法。
![](https://img-blog.csdnimg.cn/148772dc203a4ae3a73c2a48328f9153.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBATWFyc19wcmltZQ==,size_20,color_FFFFFF,t_70,g_se,x_16)
在上面的程序中,一共产生了两个Dog对象,在Dog类的run()方法中,程序创建了一个Dog对象,并使用名为d的引用变量来指向该Dog对
象;在DogTest的main()方法中,程序再次创建了一个Dog对象,并使
用名为dog的引用变量来指向该Dog对象。
这里产生了两个问题。第一个问题:在run()方法中调用jump()方
法时是否一定需要一个Dog对象?第二个问题:是否一定需要重新创建
一个Dog对象?第一个问题的答案是肯定的,因为没有使用static修饰的成员变量和方法都必须使用对象来调用。第二个问题的答案是否定
的,因为当程序调用run()方法时,一定会提供一个Dog对象,这样就
可以直接使用这个已经存在的Dog对象,而无须重新创建新的Dog对象
了。因此需要在run()方法中获得调用该方法的对象,通过this关键字
就可以满足这个要求。
this可以代表任何对象,当this出现在某个方法体中时,它所代
表的对象是不确定的,但它的类型是确定的:它所代表的只能是当前
类的实例;只有当这个方法被调用时,它所代表的对象才被确定下
来:谁在调用这个方法,this就代表谁。
将前面的Dog类的run()方法改为如下形式会更加合适。
![](https://img-blog.csdnimg.cn/b9a1c86bdd964f679cace16dbd534d6e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBATWFyc19wcmltZQ==,size_20,color_FFFFFF,t_70,g_se,x_16)
采用上面方法定义的Dog类更符合实际意义。从前一种Dog类定义来看,在Dog对象的run()方法内重新创建了一个新的Dog对象,并调用
它的jump()方法,这意味着一个Dog对象的run()方法需要依赖于另一
个Dog对象的jump()方法,这不符合逻辑。上面的代码更符合实际情
形:当一个Dog对象调用run()方法时,run()方法需要依赖它自己的
jump()方法。
在现实世界里,对象的一个方法依赖于另一个方法的情形如此常
见:例如,吃饭方法依赖于拿筷子方法,写程序方法依赖于敲键盘方
法,这种依赖都是同一个对象两个方法之间的依赖。因此,Java允许对象的一个成员直接调用另一个成员,可以省略this前缀。也就是
说,将上面的run()方法改为如下形式也完全正确
大部分时候,一个方法访问该类中定义的其他方法、成员变量时加不加this前缀的效果是完全一样的。 对于static修饰的方法而言,则可以使用类来直接调用该方法, 如果在static修饰的方法中使用this关键字,则这个关键字就无法指 向合适的对象。所以,static修饰的方法中不能使用this引用。由于 static修饰的方法不能使用this引用,所以static修饰的方法不能访 问不使用static修饰的普通成员,因此Java语法规定:静态成员不能 直接访问非静态成员。提示:省略this前缀只是一种假象,虽然程序员省略了调用jump()方法之前的this,但实际上这个this依然是存在的。根据汉语语法习 惯:完整的语句至少包括主语、谓语、宾语,在面向对象的世界 里,主、谓、宾的结构完全成立,例如“猪八戒吃西瓜”是一条汉 语语句,转换为面向对象的语法,就可以写成“猪八戒.吃(西 瓜);”,因此本书常常把调用成员变量、方法的对象称为“主调 (主语调用者的简称)”。对于Java语言来说,调用成员变量、方 法时,主调是必不可少的,即使代码中省略了主调,但实际的主调 依然存在。一般来说,如果调用static修饰的成员(包括方法、成 员变量)时省略了前面的主调,那么默认使用该类作为主调;如果 调用没有static修饰的成员(包括方法、成员变量)时省略了前面 的主调,那么默认使用this作为主调。
下面程序演示了静态方法直接访问非静态方法时引发的错误。
编译上面的程序,系统提示在info();代码行出现如下错误:
上面错误正是因为info()方法是属于实例的方法,而不是属于类的方法,因此必须使用对象来调用该方法。在上面的main()方法中直 接调用info()方法时,系统相当于使用this作为该方法的调用者,而 main()方法是一个static修饰的方法,static修饰的方法属于类,而 不属于对象,因此调用static修饰的方法的主调总是类本身;如果允 许在static修饰的方法中出现this引用,那将导致this无法引用有效 的对象,因此上面程序出现编译错误。注意:Java有一个让人极易“混淆”的语法,它允许使用对象来调用static修饰的成员变量、方法,但实际上这是不应该的。前面已经 介绍过,static修饰的成员属于类本身,而不属于该类的实例,既 然static修饰的成员完全不属于该类的实例,那么就不应该允许使 用实例去调用static修饰的成员变量和方法!所以请读者牢记一 点:Java编程时不要使用对象去调用static修饰的成员变量、方 法,而是应该使用类去调用static修饰的成员变量、方法!如果在 其他Java代码中看到对象调用static修饰的成员变量、方法的情 形,则完全可以把这种用法当成假象,将其替换成用类来调用 static修饰的成员变量、方法的代码。
局部变量与成员变量同名
大部分时候,普通方法访问其他方法、成员变量时无须使用this前缀,但如果方法里有个局部变量和成员变量同名,但程序又需要在
该方法里访问这个被覆盖的成员变量,则必须使用this前缀。
除此之外,this引用也可以用于构造器中作为默认引用,由于构造器是直接使用new关键字来调用,而不是使用对象来调用的,所以
this在构造器中代表该构造器正在初始化的对象。
在ThisInConstructor构造器中使用this引用时,this总是引用该构造器正在初始化的对象。程序中粗体字代码将正在执行初始化的
ThisInConstructor对象的foo成员变量设为6,这意味着该构造器返回
的所有对象的foo成员变量都等于6。
与普通方法类似的是,大部分时候,在构造器中访问其他成员变
量和方法时都可以省略this前缀,但如果构造器中有一个与成员变量
同名的局部变量,又必须在构造器中访问这个被覆盖的成员变量,则
必须使用this前缀。如上面的ThisInConstructor.java所示。
当this作为对象的默认引用使用时,程序可以像访问普通引用变
量一样来访问这个this引用,甚至可以把this当成普通方法的返回
值。
看下面程序:
从上面程序中可以看出,如果在某个方法中把this作为返回值,则可以多次连续调用同一个方法,从而使得代码更加简洁。但是,这
种把this作为返回值的方法可能造成实际意义的模糊,例如上面的
grow方法,用于表示对象的生长,即age成员变量的值加1,实际上不
应该有返回值。
注意:
使用this作为方法的返回值可以让代码更加简洁,但可能造成实际意义的模糊