前言
这个系列的文章主要用来记录我在学习和复习 Java 基础知识的过程中遇到的一些有趣好玩的知识点,希望大家也喜欢。
一切皆对象
对于软件工程来说面向对象编程有一套完整的解决方案:OOA、OOD、OOP, 作为程序员来讲,OOP 其实是直接接触最多的。Java 中 OOP 最直接的体现就是 java.lang.Object 了,一切都是对象(除了原生类型,原生类型的 PrimitiveClass 对象由 JVM 启动时生成和加载),Object 类主要就只有这么几个方法,其中 getClass 是反射的基石,notify、notifyAll、wait 是多线程并发时常用的方法,其中比较有意思的就是 hashCode 与 equals 了,也是面试的时候面试官很喜欢问的一个问题。
View Code
equals 与 hashCode
面试题的标准答案是:如果两个对象 a 和 b 满足 a.equals(b) == true,则它们的散列码(hash code)应当要相同,反之则不一定。这里也就引申出:重写了类的 equals 方法之后一定要重写 hashCode 方法,这种情况最常见的是在 entity bean 中,当 bean 跟容器类搭配使用时如果重写了 equals 而没重写 hashCode 就会引起问题,这里先来看看 HashMap 的 getEntry 方法,循环中就是先判断两个对象的 hash 值(由对象的 hashCode 计算得到)是否相等,再判断两个对象是否为同一对象最后才调 equals 方法来判断,这样可以减少 equals 方法的调用次数,提升容器的性能,如果大家看看 Java 容器类的源码就会发现大神们对 hash 思想的运用简直炉火纯青(生活中哈希的应用也随处可见:年月日、时分秒就是对时间流的哈希散列)
final Entry getEntry(Object key) { int hash = (key == null) ? 0 : hash(key); for (Entry e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e;
} return null;
}
下面是一张抽象化的对比图:
hashCode 一般是一个 int 值,比较两个对象的 hashCode 就是比较两个 int 值,Java 中对原生类型操作的性能肯定要好于对方法的调用,所以我们才会在 Java 容器中看到那么多对 hash 的应用。
上面这张图也可以直观看出为什么说两个对象 equals 为 true 的话 hashCode 就一定相同,反之则不一定。
equals 方法的四大特性
通过 equals 方法的注解就能清晰看到 Java 大神们给我们总结的 4 大特性了(如果在面试中遇到 equasl 和 hashCode 的问题时一遍把四大特性阐述一下会是个小小的加分项):
1、自反性:自己跟自己比较返回 true
2、对称性:x.equals(y) == y.equals(x)
3、传递性:x.equals(y) == true 且 y.equals(z) == true 则 x.equals(z) == true
4、一致性:多次调用 equals 返回结果相同
(null 与任何对象比较都应该返回 false)
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于