我的日常

登录/注册
您现在的位置:论坛 资料库 JAVA开发 > Java中的==, equals()及hashCode()
总共48087条微博

动态微博

查看: 1453|回复: 1

Java中的==, equals()及hashCode()

[复制链接]

57

主题

5

听众

129

金钱

三袋弟子

该用户从未签到

跳转到指定楼层
楼主
发表于 2015-03-04 10:04:21 |只看该作者 |正序浏览
java中的==, equals()及hashCode() 言兼原创,欢迎转载,转载请注明出处:
1. 操作符== 操作符==被用来判定两个基本类型或对象是否相等。对于基本类型和对象来说,==有完全不同的意义。
1). 用==来比较基本类型 对于两个基本类型变量来说,==比较的是两个变量的值是否相等。看下面一段简单的测试代码。
    public static void compareBasicType() {        int a = 10;        int b = 10;        short c = 10;        long d = 10;                System.out.println(a == b); //output: true        System.out.println(a == c); //output: true        System.out.println(a == d); //output: true    }上面这段测试代码中,a, b, c, d四个变量在栈上分别有自己的存储空间,四个存储空间的大小也并不都相同,但是由于它们存储的值都为10,所以最后三个比较的结果都为true。
2). 用==来比较对象 对于两个对象来说,==比较的是两个对象的引用的值,即比较两个引用是否指向同一个对象。Java对象本身存在于堆中,程序员不能直接操纵对象本身,而需要借助于引用来操纵对象。引用的值就是其所引用的对象的地址,当然Java中对象的地址是对程序员隐藏的,如果你有C/C++编程经验的话,应该很容易理解这个概念。
    public static void compareObjects() {        Object obj1 = new Object();        Object obj2 = new Object();        System.out.println(obj1 == obj2); //output: false                String str1 = new String("123");        String str2 = new String("123");        System.out.println(str1 == str2); //output: false                   str2 = str1;             System.out.println(str1 == str2); //output: true     }


上面这段测试代码中,前两个判断的输出均为false,即使str1和str2有相同的内容,两者比较依然不等,这是因为str1和str2指向的是不同的String对象。在第三个判断中,我们使str2同样指向str1所指向的对象,于是两者被判定为相等了。

另外,值得指出的是,Java不充许操作符重写(Overwrite),所以对于任何类型的对象来说,==的意义是相同的。在这一点上,equals()就不同了,见下文解释。
2. equals() 1). 概述 equals()可以用来比较两个对象,基本类型比较无法使用equals()。
Java在Object类中提供了equals()的实现,由于Java的单根继承特性,你可以在任何类中调用equals()方法。另一方面,由于equals()可能被子类重写(overwrite),所以不同的类的equals()方法可能有所不同。当然,子类也不应该随意地实现equals()方法,Java为equals()方法规定了一些需要遵守的共同约定,这在JDK文档里面有很详细的描述,摘抄于下:
The equals method implements an equivalence relation on non-null object references:
  • It is reflexive: for any non-null reference value x,  x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x,  y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

虽然,不同的类的equals()实现可能有所不同,但Object类提供的equals()实现依然值得我们来研究一下。当你没有重写这个方法的时候,调用的可能就是来自Object类的equals()方法。Object提供的equals()实现非常简单,它比较的就是两个引用的值,也就是和操作符==相同。    public static void compareObjectsWithEquals() {        Object obj1 = new Object();        Object obj2 = new Object();        System.out.println(obj1.equals(obj2)); //output: false                obj1 = obj2;        System.out.println(obj1.equals(obj2)); //output: true            }
2). 关于String的比较
String稍微有一点点的特别,但依然符合上述规则,你需要做的仅仅是弄懂一些细节。先来看一段测试代码。
    public static void compareStrings() {        String str1 = "123";        String str2 = "123";        String str3 = new String("123");                System.out.println(str1 == str2); //output: true        System.out.println(str1 == str3); //output: false        System.out.println(str1.equals(str2)); //output: true        System.out.println(str1.equals(str3)); //output: true    }对于上面的输出是否有些疑惑?事实上它依然很简单,来看看String的细节。
首先,Java中的String是一个不可修改的常量对象,Java中String维护有一个自己的常量String池。当你用String str1 = "123"这种方式创建一个String对象时,String类会查找常量池是否已存在同样的对象,如果存在则返回这个对象(因为String对象是不可变的,可以允许多个引用指向同一个对象),否则在池中创建这个对象并返回。所以,str1 == str2的结果就是true了,因为它们根本指向同一个对象。
其次,new String("123")这种方式,明确地告诉String类,我需要一个新的对象,因此它最终得到了一个新的对象。显然,str1 == str3的结果为false。
再次,String中equals()方法被Overwrite为比较String对象的内容。str1, str2及str3都具有相同的内容,所以后两个比较都为true。
最后,再看一段简单修改过的代码如下。新的创建方式使得str3同样指向了String同量池中的同一个对象,于是所有比较皆为true。事实上,这是合理的,因为str1, str2, str3指向相同的不可修改的对象,没有必要存在三份拷贝。
    public static void compareStrings() {        String str1 = "123";        String str2 = "123";        String str3 = new String("123").intern();                System.out.println(str1 == str2); //output: true        System.out.println(str1 == str3); //output: true        System.out.println(str1.equals(str2)); //output: true        System.out.println(str1.equals(str3)); //output: true    }3. hashCode() 1). 概述 hashCode()方法的作用是用来帮助HashMap,HashSet等类实现hahs table.
hashCode()同样是Object提供的一个方法,它同样可以被重写(Overwrite)。当然,子类同样不应该随意地重写这个方法。关于这个方法的实现,JDK文档给出的约定如下:
The general contract of hashCode is:
  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the  method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

对于上述约定,我们应该明白几点:
1. 一个对象的hashCode()返回值在一个Java Application的生命周期内应保持不变;
2. 两个相等(equals)的对象的hashCode值必须相等;
3. 两个不相等(!equals)的对象的hashCode值并不是一定不等,但保持不等可提高hash table的查找效率;
2). Object类实现 hashCode值一定是与对象的存储地址相关的一个值吗?不是的。Java并没有规定hashCode()的实现。只是Object类中hashCode()的实现是将对象的存储地址转换为一个int值并返回这个int值。你当然可以有自己的实现,但应该遵守前面所提及的约定。


科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
7、科帮网管理员和版主有权不事先通知发贴者而删除本文


JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

4

主题

0

听众

244

金钱

四袋长老

该用户从未签到

沙发
发表于 2015-05-08 15:38:07 |只看该作者
学习啦,学习啦
为什么回复不了啊
回复

使用道具 举报

快速回复
您需要登录后才可以回帖 登录 | 立即注册

   

关闭

站长推荐上一条 /1 下一条

发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
快速回复 返回顶部 返回列表