黑马程序员——面向对象5:this关键字

------- android培训java培训、期待与您交流! ----------

一、this关键字的作用

代码1

class Car
{
	privateString brand;
	privateint price;
 
	Car(String brand)
	{
		brand = brand;
	}
	Car{String brand, int price}
	{
		brand = brand;
		price = price;
	}
 
	public void showInfo()
	{
		System.out.println(“brand= ”+ brand +“, price = ”+price);
	}
}
 
class CarDemo
{
	publicstatic void main(String[] args)
	{
		Carc1 = new Car(“宝马”);
		c1.showInfo();
	}
}
运行上述代码,结果如下:

num = null, price = 0

       上面的结果表明了一个问题:创建Car对象时传入的实际参数“宝马”虽然赋给了构造函数中的形式参数brand,却并没有赋给堆内存中Car对象的成员变量brand。这是因为方法中的局部变量的指代总是遵循“就近原则”,例如上述代码中本意是将形式参数(局部变量)brand的值赋给对象的成员变量brand,但是由于“就近原则”,方法中的两个brand都指代的是形式参数brand,最后的结果就是形式参数brand将自己的值又赋给了自己。

       上面说了这么多,其实就一句话,“系统”自己是没法区分成员变量和局部变量的,需要程序员手动标识。

这时,就要引入一个新的关键字,“this”,并将上述代码进行修改,

代码2

class Car
{
	private String brand;
	private int price;
 
	Car(String brand)
	{
		this.brand = brand;
	}
	Car{String brand, int price}
	{
		this.brand = brand;
		this.price= price;
	}
 
	public void showInfo()
	{
		System.out.println(“brand= ”+ brand +“, price = ”+price);
	}
}
 
class CarDemo
{
	public static void main(String[] args)
	{
		Carc1 = new Car(“奔驰”);
		c1.showInfo();
	}
}
加上this后,运行结果是:

num = 奔驰, price = 0


从上面这个结果来看,构造方法中形式参数的值确实赋给了堆内存中Car对象的成员变量num。那么这里就引入可this所代表的含义:this代表本类对象。

那么,可能有的朋友就有疑问了,Car这个类的本类对象多了,只要“new”就有很多,那到底指的是谁呢?请看下面的代码,

代码3

class CarDemo2
{
	public static void main(String[] args)
	{
		Car c1 = new Car(“丰田”);
		Car c2 = new Car(“本田”);
	}
}
当创建c1所指向的Car对象时,将“丰田”作为实际参数传给了对应的构造方法,又将这个值赋给了这个构造方法内的形式参数brand,最终通过赋值语句将形式参数(局部变量)的值赋给了c1所指向的堆内存中的Car对象。这里, this就是指代了this所在方法的所属对象,换句话说, this就是指代了this所在方法的调用者。这里因为是c1所指向的对象在调用this所在的构造函数,那么this.brand指的就是c1指向的Car对象内的成员变量brand。下面的c2同理。

大家再思考一个问题,能否把代码改成c1.brand = brand呢?答案是显然是不可以的。

比如,下面的例子,

代码4

class Car
{
	private Car c = new Car();
 
	Car(String brand)
	{
		c.brand= brand;
	}
}
 
class CarDemo3
{
	public static void main(String[] args)
	{
		Car c =new Car(“雪铁龙”);
	}
}
这里构造方法c.brand = brand中的c显然不是指的主函数中的c,而是Car对象内部成员变量c,所以,换句话说,在一个对象的内部出了this关键字以外,没有别的办法可以指向本类对象。

 

小知识点1:

       代码2的运行结果是,num = 奔驰, price = 0。为什么c1.showInfo()打印的是c1所指向对象的成员变量值呢?这看起来好像很自然,大家可能会想因为是c1调用的showInfo方法,当然就是打印c1的成员变量值。其实,这里showInfo()方法是有省略的,完整的应该是这样:

System.out.println(“brand= ”+ this.brand +“, price = ”+this.price);

所以大家可以想到,之所以打印c1的成员变量值,其实是因为变量名前都省略了this,而this又是指代本类对象。所以其实,Java中是靠对象去区分成员(包括变量和方法)的所属的。因此,在对象内部调用成员,前面都省略了this。而之所以生了this主要是为了简化代码书写,但随之牺牲就是代码的阅读性了。

  总结:那说了这么多,到底什么时候显示的写this关键字呢?就是在需要指代this所在方法的调用者的时候,换句话说,哪个对象在调用this所在的方法,那么this就代表那个对象。

 

二、this关键字的应用

1. this关键字的第一个用法:代表本类对象

先看一个需求:给手机定义一个用于比较屏幕尺寸是否相同的功能。为代码简练,省去了成员变量的set和get方法,而是直接将成员变量公有,下同。代码如下:

代码5:

class Phone
{
	private float screenSize;
	private String brand;
      
	Phone(float screenSize)
	{
		this.screenSize = screenSize;
	}
	Phone(String brand)
	{
		this.brand = brand;
	}
	Phone(float screenSize, Stringbrand)
	{
		this.screenSize = screenSize;
		this.brand = brand;
	}
 
	public void showInfo()
	{
		System.out.println(“brand= ”+brand+“, screenSize = ”+screenSize);
	}
 
	public boolean compare(Phone p)
	{
		return this.screenSize == p.screenSize;
	}
}
 
class PhoneDemo
{
	public static void main(String[] args)
	{
		Phone p1 = new Phone(4.7);
		Phone p2 = new Phone(3.5f);
		System.out.println(p1.compare(p2));
	}
}
上述代码的运行结果是:false。这里,compare方法内的this就代表了,最后一行输出语句中的p1,因为是p1在调用他自己的compare方法,那么compare方法中的this就代表了调用compare方法的对象——p1。那么,我们再一次强调this的用法: 当需要在某个方法中指代这个方法的调用者时,用this关键字来表示这个调用者。大家需要注意的是,与类类型变量一样,无论p1还是this都不是对象本身,而是指向对象的Phone类类型变量。

  大家思考一个问题,上述代码Phone类的compare方法的参数列表能否改成float screenSize呢?从编译以及运行的角度来说当然是可以的。但还是不建议这样做,首先,从直观的理解上,给人一种拿手机对象(本类对象)和另一个手机对象的属性作比较的错觉,不符合生活实际;其次,直接传入屏幕尺寸,功能上比较狭窄,如果将一个手机对象传入,那么这个对象的品牌和尺寸属性就可以调用了。

 

2. this关键字的第二个用法:实现构造方法间的互相调用

大家通过观察可以发现,Phone类的三个构造方法其实是有重复的。其实,第三个构造方法的功能完全可以通过前两个构造方法来实现,没有必要再重复地写代码。那么该如何写呢?代码如下:

代码6:

class Phone
{
	private float screenSize;
	private String brand;
      
	Phone(float screenSize)
	{
		this.screenSize = screenSize;
	}
	Phone(String brand)
	{
		this.brand= brand;
	}
	Phone(float screenSize, Stringbrand)
	{
		this(screenSize);
		this(brand);
	}
 
	public void showInfo()
	{
		System.out.println(“brand= ”+ brand +“, screenSize = ”+screenSize);
	}
 
	public boolean compare(Phone p)
	{
		return this.screenSize == p.screenSize;
	}
}
 
class PhoneDemo2
{
	public static void main(String[] args)
	{
		Phone p1 = new Phone(4.7, “iPhone6”);
		p1.showInfo();
	}
}
运行结果为:

brand = iPhone, screenSize = 4.7

上述代码中黑体字部分就是修改后的代码,那么这里就引入了this关键字的第二个用法:实现构造函数之间的互相调用。这里我要引用《Java编程思想》中的解释1:通常写this的时候,都是指“这个对象”或者“当前对象”,而且它本身表示当前对象的引用。而在构造方法中,如果为this添加参数列表,那么就表示对符合此参数列表的某个构造方法的明确调用。实际上,这与普通方法的调用有相似之处,同名方法之间依靠参数列表的不同进行区别(重载)。

使用带参数列表this关键字需要注意一下三点:

1) 带参数列表的this关键字,时能用于构造方法之中,其他方法中不能使用的。

2) 带参数列表的this关键字(this()),只能定义在构造方法的第一行。要先执行构造方法内调用的其他构造方法来初始化,然后再进行其他初始化操作。

3) 不要出现下面的情况:

代码7:

class Phone
{
	Phone()
	{
		this(4.0);
	}
	Phone(float screenSize)
	{
		this();
	}
 
class PhoneDemo3
{     
	public static void main(String[] args)
	{
		Phone p = new Phone();
	}
}
上述代码一执行就会出现死循环——两个构造方法之前不停的再互相调用。

 

注释:

1.《Java编程思想》,中文第四版,Bruce Eckel著,陈昊鹏译,机械工业出版社。倒数第三行(不包括代码)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值