在QQ群里讨论了关于==和equals()的问题.

Posted on 2006-07-25 23:42 小猪 阅读(278) 评论(0)  编辑  收藏 所属分类: 读书笔记

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 ?

// 我提的问题有点钻牛角尖了,事实上两个不同类的对象之间没有比较的意义,肯定是不同的。 //

----------------------------------------------------------------------------------------------------------------------


只有注册用户登录后才能发表评论。


网站导航:
 

posts - 7, comments - 4, trackbacks - 0, articles - 0

Copyright © 小猪