2007
						年
						7
						月
						25
						日
				
				
						   
				
				星期二
				
						          
				
				晴
		
		
				----------------------------------------------------------------------------------------------------------------------
		
		
				以下是
				QQ
				群上的聊天记录,以及我的一些注释。
		
		
				
						 
				
		
		
				狂风扫落叶
				 10:23:08
		
		
				为什么
				String
				类要重写
				Object
				类的
				equals
				方法啊?
				
				
		
		
				水圣
				 10:21:14
		
		
				看看你代码
				
				
		
		
				狂风扫落叶
				 10:23:08
		
		
				不是
				,
				有朋友问我这个问题
				,
				我不知道怎么回答
				,
		
		
				好像是为了区分
				对像比较的时候
				 == 
				和
				equals 
				的有所区别
				
						  
				
		
		
				天天好心情
				 10:23:34
		
		
				==
				不是比较对象的
				
				
		
		
				阿黄
				 10:24:15
		
		
				我记得的好象是
		
		
				==
				实际上是比较的两个字符串的物理内存地址。
		
		
				“
				A
				”
				==
				“
				A
				”结果肯定是不相等的
				
				
		
		
				阿黄
				 10:24:47
		
		
				其中“
				A
				”表示一个字符串
				
				
		
		
				水圣
				 10:25:51
		
		
				==
				实际上是比较的两个字符串的物理内存地址
		
		
				
						 
				
		
		
				狂风扫落叶
				 10:25:58
		
		
				to 
				阿黄
				你说的是字符串对象,他重写了
				Object
				的
				equals
				方法
		
		
				所以会那样
				
				
		
		
				midthinker 10:26:04
		
		
				==比较对象的地址,
				equals
				比价两个对象的值(如果默认继承自
				OBJECT
				,则
				equals
				比较两个对象地址),
				String class override
				了
				Object class
				的
				equals
				方法,实现了自己的方法,所以
				equals
				比较的是实际值而非地址
				
				
		
		
				阿黄
				 10:26:45
		
		
				我说的就是这个意思了
				
				
		
		
				midthinker 10:26:54
		
		
				另外
				String class
				在
				JAVA
				中比较特殊的地方是他采取了值对象模式以及享元模式
				
				
		
		
				midthinker 10:27:25
		
		
				这意味着普通的比较会出现正确的结果
		
		
				String a = "aaa";
		
		
				String b = "aaa";
		
		
				a == b is equals 
		
		
				midthinker 10:28:33
		
		
				只觉上这个是错误的,因为
				String
				是对象,不是简单数值,所以他们应该是不同的对象,但这里他们是相同的,原因在于享元模式让
				aaa
				保留下来,并再下次使用时赋予
				
				
		
		
				midthinker 10:29:14
		
		
				但是这样就不对
		
		
				String a = new String("aaa");
		
		
				String b = new String("aaa");
		
		
				a == b is false                     //          
				其实讲到这里应该都清楚了
				object
				类的
				equals()
				跟
				==
				的作用是一样的,但是继承
				object
				类的
				子类一般都会重写
				equals()
				方法,这样做的目的是为了
				很好地区分
				equals()
				的作用,
				==
				只负责比较两个对象
				的物理地址是否相同,
				equals()
				方法负责比较两个对象
				
				
				的内容(或者说是值,
				value
				)是否相等。//
		
		
				阿黄
				 10:29:33
		
		
				这种问题应该属于比较底层的了
		
		
				没事了可以看下
		
		
				深入理解计算机系统。。。讲解很精辟
				
				
		
		
				狂风扫落叶
				 10:30:34
		
		
				受教
				
				
		
		
				水圣
				 10:33:17
		
		
				:
				"=="
				和
				equals
				方法究竟有什么区别?
		
		
				
						 
				
		
		
				==
				操作符专门用来比较变量的值是否相等。比较好理解的一点是:
		
		
				int a=10;
		
		
				int b=10;
		
		
				则
				a==b
				将是
				true
				。
		
		
				但不好理解的地方是:
		
		
				String a=new String("foo");
		
		
				String b=new String("foo");
		
		
				则
				a==b
				将返回
				false
				。
		
		
				
						 
				
		
		
				对象变量其实是一个引用,它们的值是指向对象所在的内存地址,而不是对象本身。
				a
				和
				b
				都使用了
				new
				操作符,意味着将在内存中产生两个内容为
				"foo"
				的字符串,既然是“两个”,它们自然位于不同的内存地址。
				a
				和
				b
				的值其实是两个不同的内存地址的值,所以使用
				"=="
				操作符,结果会是
				false
				。诚然,
				a
				和
				b
				所指的对象,它们的内容都是
				"foo"
				,应该是“相等”,但是
				==
				操作符并不涉及到对象内容的比较。
		
		
				对象内容的比较,正是
				equals
				方法做的事。
		
		
				
						 
				
		
		
				看一下
				Object
				对象的
				equals
				方法是如何实现的:
		
		
				boolean equals(Object o){
		
		
				
						 
				
		
		
				return this==o;
		
		
				
						 
				
		
		
				}
		
		
				Object
				对象默认使用了
				==
				操作符。所以如果你自创的类没有覆盖
				equals
				方法,那你的类使用
				equals
				和使用
				==
				会得到同样的结果。同样也可以看出,
				Object
				的
				equals
				方法没有达到
				equals
				方法应该达到的目标:比较两个对象内容是否相等。因为答案应该由类的创建者决定,所以
				Object
				把这个任务留给了类的创建者。
		
		
				
						 
				
		
		
				看一下一个极端的类:
		
		
				Class Monster{
		
		
				private String content;
		
		
				...
		
		
				boolean equals(Object another){ return
true;}
		
		
				
						 
				
		
		
				}
		
		
				我覆盖了
				equals
				方法。这个实现会导致无论
				Monster
				实例内容如何,它们之间的比较永远返回
				true
				。
		
		
				
						 
				
		
		
				所以当你是用
				equals
				方法判断对象的内容是否相等,请不要想当然。因为可能你认为相等,而这个类的作者不这样认为,而类的
				equals
				方法的实现是由他掌握的。如果你需要使用
				equals
				方法,或者使用任何基于散列码的集合(
				HashSet,HashMap,HashTable
				),请察看一下
				java doc
				以确认这个类的
				equals
				逻辑是如何实现的。
		
		
				
						 
				
		
		
				小猪
				 10:45:28
		
		
				Class Monster{
		
		
				private String content;
		
		
				...
		
		
				boolean equals(Object another){ return
true;}
		
		
				
						 
				
		
		
				}
		
		
				这个例子有点看不懂了。一个
				Monster
				的类对象怎么会去跟一个
				Object
				的类对象比较?
				
				
		
		
				小猪
				 10:45:52
		
		
				本身这样的比较就没意义吧?
				
				
		
		
				不二
				 10:46:22
		
		
				为什么没意义
				
				
		
		
				阿黄
				 10:46:41
		
		
				恩
		
		
				类好象都是从
				object
				继承来的,应该可以比较
				
				
		
		
				水圣
				 10:46:57
		
		
				比较极端而已
				
				
		
		
				阿黄
				 10:47:17
		
		
				一般的类都是默认从
				java  object
				继承
				
				
		
		
				小猪
				 10:48:21
		
		
				我小学用“像”造句
				"
				我像我爸爸
				"
				就被老师骂过啊。
				
				
		
		
				midthinker 10:48:41
		
		
				因为
				equals
				方法再
				Object class
				中的定义为
				 public boolean equals(Object
o);
		
		
				当子类方法
				override
				父类方法时,函数申明特征必须相同,所以必须使用
				Object   //
				这句话什么意思我还不是很懂。就
				Monster
				类来说
				Object
				是其父类,所以
				Monster
				的
				equals()
				的操作数必须是其父类的对象?
				//
		
		
				
						 
				
		
		
				阿黄
				 10:49:57
		
		
				呵呵
				~~~
		
		
				应该没人这样造句吧
		
		
				“我长的象我爷爷”
		
		
				嘎嘎
				~~~~~~~~~~~~~~~~~~~
		
		
				midthinker 10:50:19
		
		
				一般
				 override
equals method
				的普通手法是
		
		
				public boolean equals(Object o) {
		
		
				
						 
MyObject o = (MyObject) o;
		
		
				
						  //
TODO: compare them
		
		
				
						 
return xxx;
		
		
				} 
		
		
				水圣
				 10:50:40
		
		
				不是比喻句,但是是对的
				
				
		
		
				水圣
				 10:50:44
		
		
				哈哈
				
				
		
		
				不敗の小儜
				 10:51:29
		
		
				前面定义
				OBJECT
				应该就是说什么类都能传进去跟他比较吧。。
				
				
		
		
				小猪
				 10:52:47
		
		
				MyObject o = (MyObject) o;//
				是这句吧
				? 
		
		
				小猪
				 10:53:51
		
		
				那这个转型
				要怎么写
				? 
		
		
				midthinker 10:54:23
		
		
				是
				
				
		
		
				midthinker 10:54:33
		
		
				就是上面那句
				
				
		
		
				小猪
				 10:54:44
		
		
				这个转型怎么实现
				? 
		
		
				不敗の小儜
				 10:54:54
		
		
				。。
				
				
		
		
				midthinker 10:55:11
		
		
				呵呵语言特性,你把他理解为一个神奇的黑盒,完成你想要的功能就
				OK
				了
				
				
		
		
				小猪
				 10:55:54
		
		
				这个世界好神奇哦
				
				
		
		
				『堂』天晓得
				
10:56:10
		
		
				............................. 
		
		
				ぷ秋起雁归ぷ
				
10:56:11
		
		
				为什么这么说
				
				
		
		
				小猪
				 10:59:37
		
		
				
						 Class Monster{
		
		
				private String content;
		
		
				...
		
		
				boolean equals(Monster another){ return
true;}
		
		
				
						 
				
		
		
				}
				这样不可以么
				?
		
		
				
						 
				
		
		
				midthinker 10:55:11
		
		
				
						 
				
		
		
				危险
				...
		
		
				Monster m1 = new Monster();
		
		
				Monster m2 = new Monster();
		
		
				m1.equals(m2)
				永远相等,这真的是你想要的结果吗?
		
		
				
						 
				
		
		
				小猪
				 11:01:49
		
		
				我在
				equals()
				里面还要访问
				Monster
				的
				content
				变量的
				. 
		
		
				小猪
				 11:02:10
		
		
				比较
				content
				内容
				,
				然后再返回
				true or false 
		
		
				midthinker 11:02:39
		
		
				OK
				,这是你的业务逻辑,我不知道这对不对,你对此负责
				
						  
				
		
		
				小猪
				 11:02:41
		
		
				做到真正的内容比较是
				equals
				的职责嘛
				
				
		
		
				midthinker 11:02:51
		
		
				是的
				
				
		
		
				midthinker 11:02:59
		
		
				是内容比较,或者成为
				value
				比较
				
				
		
		
				不敗の小儜
				 11:03:40
		
		
				自己新建的类,
				equals
				比较的是引用还是内容啊。。。
				
				
		
		
				水圣
				 11:03:46
		
		
				clone 
		
		
				midthinker 11:04:04
		
		
				如果不
				override
equals method
				,默认为比较引用地址
				
				
		
		
				不敗の小儜
				 11:04:29
		
		
				Monster m1 = new Monster();
		
		
				Monster m2 = new Monster();
		
		
				m1.equals(m2) 
		
		
				不敗の小儜
				 11:04:34
		
		
				那不是不相等么
				
				
		
		
				不敗の小儜
				 11:04:41
		
		
				2
				个都
				new
				过了。。。
				
				
		
		
				midthinker 11:05:01
		
		
				他覆盖了
				equals
				方法
				
				
		
		
				不敗の小儜
				 11:05:07
		
		
				哦
				
				
		
		
				不敗の小儜
				 11:05:10
		
		
				这个是内部的?
				
				
		
		
				小猪
				 11:05:15
		
		
				语法上来说只进行类型比较吧
				?
		
		
				midthinker 11:05:38
		
		
				equals
				方法是一个
				public
				访问修饰符,所以他不应该称为内部的
				
				
		
		
				midthinker 11:05:56
		
		
				他的接口在任何时候都被共享,只要你想调用
				
				
		
		
				不敗の小儜
				 11:06:09
		
		
				哦
				
				
		
		
				小猪
				 11:12:37
		
		
				两个东西比较都是比较我们平时看得见的东西进行比较的吧
				?
				也就是外部可以访问到的东西之间的比较吧
				?
				如果两个不同的类之间包含相同的
				public
				成员变量
				.
				你是怎么实现的
				? 
		
		
				midthinker 11:14:14
		
		
				不懂你的意思?
				
				
		
		
				midthinker 11:20:08
		
		
				呵呵,假设。。。
				one
developer and one tester
				,他们密切合作,进行着紧张而忙碌的开发活动,突然你们的老板来到你们面前,并告诉你们之前程序的某个部分因为某些特殊原因发生了问题,你们的老板为此大发雷霆,甚至威胁扣除你们的奖金,除非你们能够说明谁犯了这个错误,经过分析你们发现这是一个各占
				50
				%的责任,大家认为作为一个
				developer
or Tester
				,谁更有可能优先向对方道歉,并承认错误?
				
						  
				
		
		
				小猪
				 11:21:24
		
		
				比如
		
		
				class a {
		
		
				
						 int
a=1;
		
		
				
						 
private void a(){};
		
		
				}
		
		
				
						 
				
		
		
				class b {
		
		
				
						 int
b=1;
		
		
				
						 private void b(){};
		
		
				}
		
		
				这样
				b
				里面包含了跟
				a
				一样的一个
				int 
				变量
				.
				而我们调用这两个类的时候只用到这两个类对象的
				int 
				变量的内容也就是从类的用户的角度来说这两个类是可以相等的
				.
				那么是否需要写一个
				a
				和
				b
				之间进行相等比较的
				equals method
				呢
				? 
		
		
				//
				我提的问题有点钻牛角尖了,事实上两个不同类的对象之间没有比较的意义,肯定是不同的。
				//
		
		
				----------------------------------------------------------------------------------------------------------------------