1)"=="运算符是比较两个变量的值是否相等。也就是说,该运算符用于比较变量对应的内存中所存储的值是否相等,要比较两个基础类型的数据或两个引用变量是否相等,只能使用"=="运算符。 编码
具体而言,若是两个变量是基础类型,能够直接使用"=="运算符判断对应的值是否相等。若是一个变量指向的是对象(引用类型),那么,此时涉及两块内存,对象自己占用一块内存(堆内存),变量也占用一块内存,例如对于语句String s = new String(),变量s占用一块存储空间,而new String()占用另外一块存储空间,此时变量s所对应对应内存中的存储数值就是对象占用的那块内存的首地址。对于指向类型的变量,若是判断两个变量是否指向一个相同的对象,即要比较这两个变量对应的内存中的数值是否相同(这两个变量是否指向同一个变量),这时能够经过"=="运算符来进行比较,可是若是要比较这两个对象的内容是否相等,使用"=="就没法实现了。 spa
2)equals是Object对象中的方法,每一个Java类都继承于Object,因此每个对象都具备equals方法,Object中的equals方法直接使用"=="运算符来比较两个对象,因此在没有覆盖equals方法的状况下,equals与"=="结果是同样的,都是比较对象的引用。 code
相比"=="运算符,equals方法的特殊之处就是能够被覆盖,因此能够经过覆盖,让该方法比较的不是引用,而是咱们须要的数据内容,,例如,String类中的equals方法是用于比较两个独立的对象的内容是否相同,即堆中的内容是否相等,如下面的代码为例: 对象
String s1= new String("hello"); 继承
String s2= new String("hello"); 内存
两个new语句建立了两个对象,而后分别用s1和s2指向一个对象,这是两个不一样的对象,他们的首地址是不相同的,即s1和s2存储的数值是不相同的,因此表达式s1==s2将返回false,而这两个对象的内容是相同的,因此equals方法将返回true。 md5
经过以上例子能够说明,若是一个类没有复写euqals方法,那么它就从Object中继承equals方法,而且默认使用"=="运算符来进行比较,也就是在比较两个对象的引用是否相同,所以equals和==会获得相同的结果。若比较两个独立的对象,则总会返回false。若是编写的类但愿可以比较该类建立的两个实例对象的内容是否相等,那么必须覆盖equals方法。 hash
3)hashCode()方法是从Object类中继承的,它也鉴定两个对象是否相等,Object类中的hashCode返回对象在内存中的地址的int值,因此在不重写hashcode方法时,任何对象的hashcode都是不相同的。 基础
虽然equals也是比较两个对象是否相等的,可是它和hashCode方法是有区别的。通常来说,equals方法是给用户来使用的,若是要判断两个对象是否相等,须要覆盖equals方法,而后在代码中调用,这样就能够判断它们是否相等了。对于hashCode方法用户通常是不会调用它的,例如在hashMap中,因为key是不重复的,它在判断key是否重复的时候就调用了hashCode方法,并且也用类equals方法。此处不可重复,指的是,equals和hashCode方法中的一个不相同就能够了。因此hashCode相等于一个对象的编码表,就好像文件中的md5,它与equals方法的区别在于它的返回值是int类型,比较起来不直观。 变量
通常在覆盖equals方法的同时也一样须要覆盖hashCode方法,不然,就会违反Object.hashCode的通用规则约定,从而致使没法与全部基于散列表的集合类(hashMap hashSet hashTable)结合在一块儿正常使用。
hashCode方法和equals方法的关系以下:若是x.equals的返回值true,即两个对象经过equals方法比较是相同的,那么调用两者的hashCode方法将返回相同的int值。若是x.equals的返回值false,即两个对象经过quals方法比较的结果是不相同的,那么x,y的hashCode的返回值可能相等也可能不相等。反之,hashCode的返回值不相等,必定能够推出equals方法的返回值是不相等的,而hashCode的返回值相等,equals的返回值可能相等也可能不相等。