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
呢
?
//
我提的问题有点钻牛角尖了,事实上两个不同类的对象之间没有比较的意义,肯定是不同的。
//
----------------------------------------------------------------------------------------------------------------------