目录javascript
默认状况下也就是从超类Object继承而来的equals()方法与‘==’是彻底等价的, 比较的都是对象的内存地址.java
但咱们能够重写equals()方法, 使其按照咱们的需求的方式进行比较, 好比String类就重写了equals方法, 它比较的是字符的序列, 而再也不是内存地址.api
自反性、对称性、传递性等都是 <集合论> 中的概念. 数组
(1) 自反性: 对于任何非null的引用值x, x.equals(x)应返回true.安全
(2) 对称性: 对于任何非null的引用值x与y, 当且仅当:y.equals(x)返回true时, x.equals(y)才返回true.ide
(3) 传递性: 对于任何非null的引用值x、y与z, 若是y.equals(x)返回true, y.equals(z)返回true, 那么x.equals(z)也应返回true.性能
(4) 一致性: 对于任何非null的引用值x与y, 假设对象上equals比较中的信息没有被修改, 则屡次调用x.equals(y)始终返回true或者始终返回false.this
(5) 对于任何非空引用值x, x.equal(null)应返回false..net
这个问题主要和映射(Map接口)相关. 咱们知道Map接口的类会使用到键(Key)的哈希码, 当咱们调用put()/get()
方法操做Map容器时, 都是根据Key的哈希码来计算存储位置的, 所以若是咱们对哈希码的获取没有相关保证, 就可能会得不到预期的结果.code
在Java中, 咱们能够经过hashCode()
方法获取对象的哈希码, 哈希码的值就是对象的存储地址, 这个方法在Object类中声明, 所以全部的子类都含有该方法.
hashCode就是哈希码(或者散列码), 是由对象导出的一个整型值, 哈希码是没有规律的, 若是x与y是两个不一样的对象, 那么x.hashCode()与y.hashCode()就不会相同 —— 只要x和y对象没有重写hashCode()方法, JVM规范中明确要求它们的散列码不会相同.
String(字符串)的哈希码是由字符串的内容导出的, 也就是String类中重写了hashCode()方法.
(1) Java发布者但愿咱们使用更加安全的调用方式来返回散列码, 也就是使用null安全的java.util.Objects.hashCode()
方法, 这个方法的优势是若是参数为null, 就只返回0, 不然返回对象参数调用的hashCode的结果.
Objects.hashCode()的源码以下:
public static int hashCode(Object o) { return o != null ? o.hashCode() : 0; }
(2) JDK 7中还提供了一个方法: java.util.Objects.hash(Object... objects)
, 当须要组合多个散列值时能够调用该方法, 好比:
public class Model { private String name; private double salary; private int sex; // @Override // public int hashCode() { // return Objects.hashCode(name) + new Double(salary).hashCode() + new Integer(sex).hashCode(); // } @Override public int hashCode() { return Objects.hash(name, salary, sex); } }
扩展: 若是咱们提供的是一个数值类型的变量, 那么咱们能够调用Arrays.hashCode()
方法来计算它的散列码, 这个散列码是由数组中各个元素的散列码组成的.
—— 内容摘自《Java深刻解析》.
(1) 在Java应用程序执行期间, 若是在equals()方法中涉及到的信息没有被修改, 那么在同一个对象上屡次调用hashCode()方法时必须一致地返回相同的整数. 若是屡次执行同一个应用程序时, 不要求该整数必须相同.
(2) 若是两个对象经过调用equals()方法是相等的, 那么这两个对象调用hashCode()方法必须返回相同的整数.
(3) 若是两个对象经过调用equals()方法是不相等的, 不要求这两个对象调用hashCode()方法必须返回不一样的整数. 可是开发人员应该意识到: 对不一样的对象产生不一样的hash值能够提升哈希表的性能.
在重写equals()
方法时, 通常推荐使用getClass()
来进行类型判断, 而不是使用instanceof
关键字.
除非全部的子类有统一的语义才使用
instanceof
, 统一的语义就是说, 不一样的子类在equals()
方法中比较的内容相同.
咱们知道, instanceof
关键字的做用是判断其左边对象是否为其右边类型的实例, 返回boolean类型的数据, 它多用来判断继承关系中的某个子类的实例是否为父类的实现.
—— 摘自《Java核心技术 第一卷:基础知识》.
(1) 显式参数命名为otherObject, 稍后须要将它转换成另外一个叫作other的变量 (参数名命名, 强制转换请参考下一条建议);
(2) 将otherObject转换为相应的类类型变量: ClassName other = (ClassName) otherObject;
;
(3) 检测this与otherObject是否引用同一个对象: if(this == otherObject) return true;
—— 存储地址相同, 确定是同个对象, 直接返回true;
(4) 检测otherObject是否为null , 若是为null, 返回false: if(otherObject == null) return false;
;
(5) 比较this与otherObject是否属于同一个类(视需求而选择):
① 若是equals的语义(能够理解为equals比较的内容)在每一个子类中有所改变, 就使用getClass检测:
if(getClass() != otherObject.getClass()) return false;
② 若是全部的子类都拥有统一的语义(比较的内容不变), 就使用instanceof检测:
if(!(otherObject instanceof ClassName)) return false;
(6) 对全部须要比较的域进行比较: 使用==比较基本类型域, 使用equals比较对象域. 若是全部的域都匹配, 就返回true, 不然就返回flase:
① 若是在子类中从新定义equals()方法, 就要在其中包含调用
super.equals(other)
;② 当此方法被重写时, 一般有必要重写 hashCode() 方法, 以维护 hashCode 方法的常规协定, 该协定声明 相等对象必须具备相等的哈希码
参考资料
版权声明
做者: 马瘦风
出处: 博客园 马瘦风的博客
感谢阅读, 若是文章有帮助或启发到你, 点个[好文要顶👆] 或 [推荐👍] 吧😜
本文版权归博主全部, 欢迎转载, 但 [必须在文章页面明显位置给出原文连接], 不然博主保留追究相关人员法律责任的权利.