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
呢
?
//
我提的問題有點鉆牛角尖了,事實上兩個不同類的對象之間沒有比較的意義,肯定是不同的。
//
----------------------------------------------------------------------------------------------------------------------