我问的是非常基本的问题,但是真的很困惑equals方法在java中是如何工作的。让我举一个例子,我在类级别声明类型为String的三个变量。
String a = "abc";
String b = "abc";
String c = new String("abc");
然后根据java拇指规则编写一个比较它们的方法。
public void compare(){
System.out.println("a.equals(c) :" + a.equals(c));
System.out.println("a == b :" + (a == b));
System.out.println("a == c :" + (a == c));
}
现在,当我运行该程序时,它给了我以下输出。
a.equals(c) :true
a == b :true
a == c :false
现在我很困惑,因为我知道写成文字的字符串总是被创建到StringPool中。这意味着变量a和b将被创建为StringPool,并且根据stringPool,将只有一个实例,变量a和b将指向此变量。变量c将被创建到堆内存中。当我比较a.equals(c)时,它给了我真实的可能性,因为equals的默认实现总是比较内存分配而不是内容。它应该返回false。
我也在为整数做同样的事情,比如
Integer m = 1;
Integer n = 1;
Integer o = new Integer(1);
public void compareInt(){
System.out.println("m.equals(o) :" + m.equals(o));
System.out.println("m == n :" + (m == n));
System.out.println("m == o :" + (m == o));
}
out is
m.equals(o) :true
m == n :true
m == o :false
现在再次感到困惑。所有三个变量都将被创建到头部内存中,因为对于整数,现在有IntegerPool。然后m == n如何给出真实,因为再次==运算符比较引用而不是内容,并且根据我的理解参考是不同的。在这种情况下,equals方法的行为与String中的相同。
可以帮助了解正在发生的事情。
答案 0 :(得分:6)
字符串和整数覆盖equals
方法,因此它们不依赖于默认实现。
例如,这里是String :: equals:
的实现public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
哦,整数确实有-128到127之间的值的缓存,这解释了为什么m==n
返回true。