==
对于基本数据类型来说,主要是匹配值是否相同。
1 | ini复制代码public class Equals { |
输出结果如下:
1 | arduino复制代码true |
对于引用类型来说,==匹配的是两个是否指向了同一内存区域。
1 | java复制代码public class Equals { |
上述通过new关键字分别创建了2个对象,此时我们用==进行比较,结果如下
1 | arduino复制代码false |
这里涉及到对象创建的只是了,后续在虚拟机相关笔记中体现。
equal
equals
是 Java 中所有对象的父类,即 Object
类定义的一个方法。它只能比较对象,它表示的是引用双方的值是否相等。
1 | csharp复制代码public class Equals { |
equals 用作对象之间的比较具有如下特性
自反性
:对于任何非空引用 x 来说,x.equals(x) 应该返回 true。对称性
:对于任何非空引用 x 和 y 来说,若x.equals(y)为 true,则y.equals(x)也为 true。传递性
:对于任何非空引用的值来说,有三个值,x、y 和 z,如果x.equals(y) 返回true,y.equals(z) 返回true,那么x.equals(z) 也应该返回true。一致性
:对于任何非空引用 x 和 y 来说,如果 x.equals(y) 相等的话,那么它们必须始终相等。非空性
:对于任何非空引用的值 x 来说,x.equals(null) 必须返回 false。
String的equal实现
String也是在日常编程中经常使用的修饰符之一,它和其它基本数据类型不同,String本身是一个常量(final),其不能被其他对象所继承(至于原因,据说是开发者觉得String实现已经非常完美了,不想开发者任意扩展来破坏它),其一经赋值便无法再改变,继承自Object,所以Object具有的能力在String中都可以找到相对于的。
此处我们重点分析,String中的equal实现。
1 | arduino复制代码public boolean equals(Object anObject) { |
String中equals的实现总结来说可以是以下几点:
1.判断是否传入的是自身,如果是返回true。
2.判断是否是String对象,如果不是返回true。
2.1 如果是String对象 则比较传入的len是否一致,如果一致,则继续比较。
2.2 比较字符,如果字符不一致,则返回false,反之继续比较直到比较完全(这里是一个循环全量匹配)
这里再提示一下,你可能有疑惑什么时候是
1 | kotlin复制代码if (this == anObject) { |
这个判断语句如何才能返回 true?因为都是字符串啊,字符串比较的不都是堆空间吗,猛然一看发现好像永远也不会走,但是你忘记了 String.intern()
方法,它表示的概念在不同的 JDK 版本有不同的区分
在 JDK1.7 及以后调用 intern 方法是判断运行时常量池中是否有指定的字符串,如果没有的话,就把字符串的引用添加到常量池中,并不是复制一份对象放入其中了。
重写HashCode
equals 方法和 hashCode 都是 Object 中定义的方法,它们经常被一起重写。
equals 方法是用来比较对象大小是否相等的方法,hashcode 方法是用来判断每个对象 hash 值的一种方法。如果只重写 equals 方法而不重写 hashcode 方法,很可能会造成两个不同的对象,它们的 hashcode 也相等,造成冲突。比如
1 | ini复制代码String str1 = "通话"; |
上述两个字符串所代表的hashcode就是相同的。
1 | 复制代码1179395 |
它们两个的 hashcode 相等,但是 equals 可不相等。
关于equals总结如下
- 如果在 Java 运行期间对同一个对象调用 hashCode 方法后,无论调用多少次,都应该返回相同的 hashCode,但是在不同的 Java 程序中,执行 hashCode 方法返回的值可能不一致。
- 如果两个对象的 equals 相等,那么 hashCode 必须相同
- 如果两个对象 equals 不相等,那么 hashCode 也有可能相同,所以需要重写 hashCode 方法,因为你不知道 hashCode 的底层构造(后续可以解析jvm源码深入认识hashcode的构造),所以你需要重写 hashCode 方法,来为不同的对象生成不同的 hashCode 值,这样能够提高不同对象的访问速度。
- hashCode 通常是将地址转换为整数来实现的。
本文转载自: 掘金