关于Java中的equals方法
欢迎转载,但是请填写本人的博客园原址https://www.cnblogs.com/JNovice/p/9347099.html
一、什么是equals方法
equals方法是Object类中的方法,根据Java的技术文档上的描述,其作用指示其他某个对象是否与此对象“相等”。
equals方法在非空对象引用上实现相等关系:
自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回 false
Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。
注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
参数: obj - 要与之比较的引用对象。
返回: 如果此对象与 obj 参数相同,则返回 true;否则返回 false。
二、equals的重写
(一)为什么要重写equals方法
1 //Obeject未被重写时equals方法的源码,StringBuffer的equals方法也是一样的,也未重写
2 public boolean equals(Object obj) {
3 return (this == obj);
4 }
从源码中我们可以看出,equals未被重写的时候,它的作用是用来比较两个引用数据类型的对象的引用是否相同。
但是我们实际开发中,更多的是两个对象的具体数值是否相同,当两个对象的具体值相同时,我们一般就认为它们是相等的,所以我们需要去重写equals方法
(二)String类中对equals方法的重写
1 //个人String的equals方法的源码的简单解读
2 public boolean equals(Object anObject) {
3 if (this == anObject) {//先对地址值进行判断
4 return true;
5 }
6 if (anObject instanceof String) {//判断传入是否是字符串类型
7 String anotherString = (String)anObject;
8 int n = value.length;//此value时String的内部属性,是存储String字符串的char型数组
9 if (n == anotherString.value.length) {//判断传入的字符串长度与本对象是否相等
10 char v1[ ] = value;
11 char v2[ ] = anotherString.value;
12 int i = 0;
13 while (n-- != 0) {//将字符串的每个字符进行比较
14 if (v1[i] != v2[i])
15 return false;
16 i++;
17 }
18 return true;
19 }
20 }
21 return false;//以上都没有return的代表都不满足if条件,最终返回false
22 }
23 }
我们再将String重写过后的equals源码和和未重写的进行比较,我们就可以发现重写之后的String的equals方法是原方法的升级版。
首先它也对两个引用进行了比较,同时也比较了String的具体数值,当满足既是字符串类型又和本字符串的长度和具体内容全都相同时,那么此时才返回true
(三)Java10.0的String类的equals方法
1 //Java10.0版本对equals重写的简单解读
2 public boolean equals(Object anObject) {
3 if (this == anObject) {
4 return true;
5 }
6 if (anObject instanceof String) {
7 String aString = (String)anObject;
8 if (coder() == aString.coder()) {
9 return isLatin1() ? StringLatin1.equals(value, aString.value)//这里的Latin1是ISO-8859-1编码格式的别称
10 : StringUTF16.equals(value, aString.value);
11 }
12 }
13 return false;
14 }
这里Java10.0版本对String类的equals方法进行了升级。
因为10.0版本的equals方法加入对编码格式的判定,这里的编码格式是Latin1(别名ISO-8859-1)和UTF-16。
注:以下列举几个其他的编码格式
ASCII 英文字符集
Unicode 国际通用字符集,注意Java语言是用Unicode编写的
UTF-8
8-bit Unicode Transformation Format是一种针对Unicode的可变长度字符编码
BIG5 台湾的大五码,表示繁体汉字
GB2312 大陆使用最早、使用最广的简体中文字符集
GBK GB2312的扩展,可以表示繁体中文
GB18030 最新GBK拓展,中国所有非手持/嵌入式计算机系统的强制实施标准,可以表示汉字、维吾尔语、藏文等中华民族字符
三、equals方法和==在判断相等上的区别
==既可以判断基本数据类型,又可以判断引用数据类型,判断基本数据类型时是判断值是否相等,而判断引用数据类型时是判断引用地址是否相等
equals方法只能判断引用数据类型是否相等,在未被重写时与==的判断方式一致,但是被重写之后不仅判断引用是否,而且判断对象的具体属性值是否相等
注:所有我们在判断String等引用数据类型是否相等时时一般都是用重写后的equals的方法,还有StringBuffer的equals方法未被重写
以下是实际代码演示
1 public class TestClass {
2
3 public static void main(String[] args) {
4 String s1 = "123";
5 String s2 = new String("123");
6 System.out.println(s1 == s2);//由于s2是在堆空间的引用,因而和s1的引用地址不一样
7 System.out.println(s1.equals(s2));
8 //结果输出
9 //false
10 //true
11
12 String s3 = "abc";
13 String s4 = "abc";
14 System.out.println(s3 == s4);//由于字符串是不可变的,当常量池中有这个字符串数值,就不再创建直接将引用给新的字符串对象
15 System.out.println(s3.equals(s4));
16 //结果输出
17 //true
18 //true
19 }
20
21 }
注:补充下其他的数据类型如何对比
整型可以用==进行对比
字符串用equals进行对比
浮点型可以使用BigDecimal或者浮点型的包装类方法Float.floatToIntBits和Double.doubleToLongBits方法
getHashCode方法