A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张忠豹 中级黑马   /  2012-10-22 18:31  /  5897 人查看  /  19 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张忠豹 于 2012-10-23 19:40 编辑

class A{
        public int hashCode(){
                return 60;
        }
}
public class HashSetDemo1 {
        public static void main(String args[]){
                A a1 = new A();
                A a2 = new A();
                //day29.A@3c^^^^^^day29.A@3c
                System.out.println(a1.toString()+"^^^^^^"+a2.toString());
                System.out.println(a1==a2);//false
                System.out.println(a1.equals(a2));//false
        }
}
看了好几个哥们的答案,感觉说的和我问的不一样!
a1==a2为什么返回false,a1不是指向一个对象的引用吗,这个引用应该就是地址值吧(地址值应该是hashcode吧),它们两的hashcode一样,为什么还不对?
在Object类中equals源代码为:
public boolean equals(Object obj) {
return (this == obj);
    }
比较时也用==号,==比较的不是hashcode吗?

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1

查看全部评分

19 个回复

倒序浏览
equals比较的是字符串,a1,a2类,当然会出错了
回复 使用道具 举报
“==”是进行数值比较的;
equals()常用的是进行字符串比较的,
而两个对象之间的比较野可以用equals()但是的进行方法的重写,这个就比较麻烦了。
回复 使用道具 举报
  1. class A{
  2.     public int hashCode(){
  3.             return 60;
  4.     }
  5. }
  6. public class HashSetDemo1 {
  7.     public static void main(String args[]){
  8.             A a1 = new A();
  9.             A a2 = new A();
  10.             //day29.A@3c^^^^^^day29.A@3c
  11.             System.out.println(a1+"^^^^^^"+a2);
  12.             System.out.println(a1.hashCode()==a2.hashCode());//true
  13.             System.out.println(a1.toString().equals(a2.toString()));//true
  14.     }
  15. }
复制代码
int 、 String的比较,看代码,你就明白了。
回复 使用道具 举报
equals 是继承超类object的方法,不复写的情况写默认都是比较内存地址,你上面是开辟了两个内存地址,所以说用equals比较是false, String中就复写了equals方法,可以比较字符串是否相等

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 梁枝武 于 2012-10-22 23:05 编辑

{:soso_e143:}学习了
回复 使用道具 举报
李铁 中级黑马 2012-10-22 21:44:37
7#
本帖最后由 李铁 于 2012-10-22 21:47 编辑

class A{
         public int hashCode(){
                 return 60;
         }
}
public class HashSetDemo1 {
         public static void main(String args[]){
                 A a1 = new A();
                 A a2 = new A();
                 [url=]//day29.A@3c^^^^^^day29.A@3c[/url]:只是对象的内容相等,也就是hashCode,
                 System.out.println(a1.toString()+"^^^^^^"+a2.toString());
                 System.out.println(a1==a2);//false--->原因是它们的句柄不相同的。
                 System.out.println(a1.equals(a2));//
              false-->原因是equals()的默认行为比较句柄,你没有在你的类中重写equals();当然就不相等;只有你重写了equals()方法,比较才是内容,而非句柄
              public boolean equals(Object obj) {
                 return (this == obj);//此处比较是句柄
                           }   
         }
}

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1

查看全部评分

回复 使用道具 举报
equals方法只在一些特定类中才可以直接使用,因为这些类中重写了上帝类Object中的这个方法,改变了它实现的功能,所以它才可以用来比较引用变量的值,而在你定义的类A中并没有重写这个方法,所以它实现的功能还是Object了中的,而这时equals方法比较的就是地址值了,和“==”的效果一样,你定义了两个对象,内存里就会出现两个地址值,所以就都是false
回复 使用道具 举报
杨志男 发表于 2012-10-22 21:48
equals方法只在一些特定类中才可以直接使用,因为这些类中重写了上帝类Object中的这个方法,改变了它实现的 ...

既然你也说了==和没有重写的equals比较的都是地址值,那么地址值不是   类名@哈希码?
我的程序中创建的对象类名肯定是一样的,而且我将对象的hashCode方法也重写了,所以  类名@哈希码应该是相等的,为什么出错了。难道地址值不是  类名@哈希码?
回复 使用道具 举报
李铁 发表于 2012-10-22 21:44
class A{
         public int hashCode(){
                 return 60;

句柄是个什么东西?求解释!
回复 使用道具 举报
乔九 中级黑马 2012-10-22 23:19:52
11#
class A{
         public int hashCode(){
                 return 60;
         }
}
public class HashSetDemo1 {
         public static void main(String args[]){
                 A a1 = new A();
                 A a2 = new A();
                 //day29.A@3c^^^^^^day29.A@3c
                 System.out.println(a1.toString()+"^^^^^^"+a2.toString());
                 System.out.println(a1==a2);//false此处的a1和a2为不同的对象在堆中的创建位置是不同的所以为false
                 System.out.println(a1.equals(a2));//false此处比较的为a1和a2所引用的地址值并非他们的内容
         }
}

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1

查看全部评分

回复 使用道具 举报
李铁 中级黑马 2012-10-22 23:25:44
12#
张忠豹 发表于 2012-10-22 23:18
句柄是个什么东西?求解释!

对象的引用
回复 使用道具 举报
{:soso_e100:}
回复 使用道具 举报
乔九 发表于 2012-10-22 23:19
class A{
         public int hashCode(){
                 return 60;

在堆中创建的对象是不同的……
创建对象后,赋值给对象变量的时候,不是传递的地址值吗?
创建对象的位置,不就是用地址值来区分的吗?类名@hashcode就是对象的地址值吧。
a1和a2,类名@hashcode应该都是一样的啊?
回复 使用道具 举报
乔九 中级黑马 2012-10-22 23:51:01
15#
张忠豹 发表于 2012-10-22 23:34
在堆中创建的对象是不同的……
创建对象后,赋值给对象变量的时候,不是传递的地址值吗?
创建对象的位置 ...

你可看看java内存分配机制
回复 使用道具 举报
A a1 = new A();
A a2 = new A();
你的程序中创建的对象类名是一样的,但不是同一个对象啊,就像是同名不同人。这里在堆中开辟了两个内存地址,创建了两个对象,a1、a2代表对象的引用

System.out.println(a1==a2);//false  对象的引用不同
System.out.println(a1.equals(a2));//false比较两个引用类型是否引用同一对象
== 运算符是一个可由类重载的运算符,该类通常具有恒等行为。
对于未重载 == 的引用类型,该运算符会比较两个引用类型是否引用同一对象,而这恰好是 java.lang.object 中的 equals 实现所做的工作。

如果你重写你的equals方法,根据你的需要重载结果就不一样了
回复 使用道具 举报
黑马杨锦喜 发表于 2012-10-23 01:03
A a1 = new A();
A a2 = new A();
你的程序中创建的对象类名是一样的,但不是同一个对象啊,就像是同名不 ...

内存地址……
内存地址不是这样的吗?
类名@hashCode
两个对象的   类名@hashCode 一样啊?怎么还是false
回复 使用道具 举报
张忠豹 发表于 2012-10-23 15:42
内存地址……
内存地址不是这样的吗?
类名@hashCode

     如果不重写equals,那么比较的将是对象的引用是否指向同一块内存地址,重写之后目的是为了比较两个对象的value值是否相等。
      两个对象的hashCode相等,用equals运算就一定相等吗?不一定!
      哈希码在生成的时候胡产生冲突的。

     hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储  对象的hashcode值来进行判断是否相同的。这样如果我们对一个对象重写了euqals,意思是只要对象的成员变量值都相等那么euqals就等于true,但不重写hashcode,那么我们再new一个新的对象,当原对象.equals(新对象)等于true时,两者的hashcode却是不一样的,由此将产生了理解的不一致,如在存储散列集合时(如Set类),将会存储了两个值一样的对象,导致混淆,因此,就也需要重写hashcode。为了保证这种一致性,必须满足以下两个条件:
    (1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true
    (2)当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false

如果你硬要弄个为什么,我觉得自己也糊涂了。看下这里http://www.doc88.com/p-808812147971.html
回复 使用道具 举报
我创建的两个对象不是放在HashSet集合中的,所以重不重写equals,好像没有关系的。算了就此结贴……
回复 使用道具 举报
张忠豹 发表于 2012-10-22 23:18
既然你也说了==和没有重写的equals比较的都是地址值,那么地址值不是   类名@哈希码?
我的程序中创建的 ...

不错,这2个方法都是用来判断2个对象是否相等的。但是他们是有区别的:
一般来讲,equals这个方法是给用户调用的,如果你想判断2个对象是否相等,你可以重写equals方法,然后在代码中调用,就可以判断他们是否相等了。简单来讲,equals方法主要是用来判断从表面上看或者从内容上看,2个对象是不是相等。举个例子,有个学生类,属性只有姓名和性别,那么我们可以认为只要姓名和性别相等,那么就说这2个对象是相等的。
hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了hashcode这个方法,而且也用到了equals方法。这里不可以重复是说equals和hashcode只要有一个不等就可以了!所以简单来讲,hashcode相当于是一个对象的编码,就好像文件中的md5,他和equals不同就在于他返回的是int型的,比较起来不直观。我们一般在覆盖equals的同时也要覆盖hashcode,让他们的逻辑一致。举个例子,还是刚刚的例子,如果姓名和性别相等就算2个对象相等的话,那么hashcode的方法也要返回姓名的hashcode值加上性别的hashcode值,这样从逻辑上,他们就一致了。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马