下面是String.equals()方法的源码
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
通过比较hashCode和对每一个字符的比较,确定两个字符串时候是相等的。
看contentEquals()源码,从上到下依次为方法1和方法2
public boolean contentEquals(StringBuffer sb) {
synchronized (sb) {
return contentEquals((CharSequence) sb);//这是一个重载方法的调用,也就是下面的源代码
}
}
public boolean contentEquals(CharSequence cs) {
if (value.length != cs.length())
return false;
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
char v1[] = value;
char v2[] = ((AbstractStringBuilder) cs).getValue();
int i = 0;
int n = value.length;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
// Argument is a String
if (cs.equals(this))
return true;
// Argument is a generic CharSequence
char v1[] = value;
int i = 0;
int n = value.length;
while (n-- != 0) {
if (v1[i] != cs.charAt(i))
return false;
i++;
}
return true;
}
这两个重载方法的区别在于参数的不同,方法1接受一个StringBuffer类型的参数,方法2接收一个CharSequence接口类型的参数,也就是说方法2可以接收任何实现了该接口的参数
我们常用的不多,String、StringBuffer、StringBuilder都可以。
方法1是对方法2的调用。
而方法1中使用到了关键字 synchronized
public boolean contentEquals(StringBuffer sb) {
synchronized (sb) {
return contentEquals((CharSequence) sb);
}
}
我的理解是,StringBuffer是一个可变字符串,且线程不安全,在并发情况下,调用这个方法就不得不靠考虑安全性,因此使用synchronized对该对象加锁,在执行的时候不允许其他线程去修改它,保证程序不出现问题。