为什么要使用equals()方法,而不是使用==运算符?
在Java中,==
操作符用于比较对象的引用,判断两个引用是否指向同一个对象。而equals()
方法用于比较对象的内容,判断两个对象是否表示相同的概念。
然而,在比较值类型时,情况就不同了。在Java中,没有所谓的"值类型",除非我们在谈论基本类型。基本类型没有equals()
方法,只有其对应的包装类型才有。而且,如果比较的是数字,结果也只会是相等或不相等,具体取决于数字的大小。
简单来说,==
操作符用于比较对象的引用,而equals()
方法用于比较对象的内容。在比较值类型时,要注意使用对应的包装类型进行比较。
以下是一个示例代码:
System.out.println(new Integer(55).equals(new Integer(55))); System.out.println(new Integer(5555).equals(new Integer(555)));
输出结果为:
true false
为什么我们有了==运算符还需要equals()方法?
在处理基本类型的情况下,==运算符检查两个值是否相同。
如果不是基本类型,则检查两个指针(或引用)是否指向同一个对象的实例。
equals()方法执行自定义检查,对于Object类来说,它通过使用==来检查引用。但是在其他类中,equals()方法有时会被重写。equals()方法必须检查内容。
例如:
int i0 = 34;
int i1 = 34;
int i2 = 35;
结果:
i0 == i1: true
i1 == i0: true
i2 == i0: false
但是,如果我们有非基本类型:
String str0 = new String("Hello man!");
String str1 = new String("Hello man!");
String str2 = new String("!nam olleH");
String str2copy = str2;
结果:
str0 == str1: false //指向两个不同的对象,所以==返回false
str1 == str2: false //同上
str2 == str2copy: true //这是指向同一个对象的两个指针
str0.equals(str1): true //这两个对象不同,但是它们是相等的
str1 == str1: true //再次,两次指向同一个对象
那么,为什么str0.equals(str1)返回true?因为String类重写了equals()方法。在该方法中,它不会通过return this == obj;来检查它们是否相等。但是在该方法中,有一个完整的检查。我不知道他们用什么方法来比较这两个字符串,但有两种可能的方式:
1. 从这两个字符串生成一个哈希码并检查它们是否相等(int == int);
2. 逐个字符地检查它们是否相同。
所以我希望现在这一点已经很清楚了。
补充说明一下,使用字符串字面量时,行为会有所不同:
String str0 = "Hello man!";
String str1 = "Hello man!";
str0 == str1;
返回true,因为JVM将字面量字符串对象放在字符串池中。因此,str1和str2都指向池中的同一个对象。
这里挑剔一下,根据定义,两个值永远不可能相同(否则,它只会是一个值)。
为什么在有==运算符的情况下还需要equals()方法?
在Java中,==运算符用于比较两个对象的引用是否相等,即判断两个对象是否指向同一个内存地址。而equals()方法用于比较两个对象的内容是否相等,即判断两个对象的字段值是否相同。
然而,==运算符无法被重载,因此无法改变其比较方式。如果想要改变比较方式,需要重写equals()方法。通过重写equals()方法,可以根据对象的字段值来判断对象是否相等。
另外,如果重写了equals()方法,还需要同时关注hashCode()方法。这两个方法需要保持一致性,即如果两个对象根据equals()方法判断相等,则它们的hashCode()方法返回的值也应相等。否则,在将对象添加到集合或映射中时可能会出现各种奇怪的错误。
如果不重写equals()方法,则默认情况下equals()方法会和==运算符具有相同的行为,即比较对象的引用是否相等。这种情况下,如果实例化了两个具有相同字段值的对象,并将这些字段值设置为相同,那么比较它们的相等性仍然会返回false。只有通过重写equals()方法,才能根据字段值来判断对象是否相等。
需要注意的是,相等性和身份性是不同的概念。两张十元纸币在货币模型中是相等的,但它们不是同一张纸币。
为了改变比较方式并实现对象内容的相等性判断,需要重写equals()方法。同时,还需要保持equals()方法和hashCode()方法的一致性。这样才能确保在集合或映射中正确地使用对象。