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;
}
equals方法非常重要,很多考菜鸟的面试题都会问==和equals什么区别,然后一些官方答案就是==判断的是引用,equals判断的是值,其实要是看了源代码,不会说出这么浅显的答案。String重写了Object的equals方法,String的equals方法首先判断是不是同一个对象,如果是就返回true。接下来判断参数是否是String类对象,不是的话就返回false,是的话先进行强转,然后获取String的char数组value的长度,如果两者的char数组value的长度不一样,也将返回false,然后用while循环判断两个char数组的每一个元素是否相等,如果不等就返回false。
public boolean contentEquals(StringBuffer sb) {
return contentEquals((CharSequence)sb);
}
private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
char v1[] = value;
char v2[] = sb.getValue();
int n = v1.length;
if (n != sb.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != v2[i]) {
return false;
}
}
return true;
}
public boolean contentEquals(CharSequence cs) {
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
synchronized(cs) {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
} else {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
}
// Argument is a String
if (cs instanceof String) {
return equals(cs);
}
// Argument is a generic CharSequence
char v1[] = value;
int n = v1.length;
if (n != cs.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != cs.charAt(i)) {
return false;
}
}
return true;
}
这三个方法要一起看,第一个方法调用了第三个方法,第二个方法其实就是equals方法内部的实现,很奇怪干嘛单提出来,看来甲骨文也有不巧妙的地方,当然也许我水平低看不出人家的玄机。
第三个方法是判断内容相等与否。传入一个CharSequence对象cs,判断该对象是不是AbstractStringBuilder的子类,StringBuffer和StringBuilder都继承自AbstractStringBuilder类,然后AbstractStringBuilder类又实现了CharSequence接口。
如果确实是AbstractStringBuilder的子类,则判断是否为StringBuffer,如果是StringBuffer那么先给cs上锁,用上面的第二个方法进行判断,如果不属于StringBuffer,则直接用上面第二个方法判断。
为什么要给cs加锁呢?StringBuffer不是线程安全的么?没错,StringBuffer内部方法都是同步方法,但是如果cs作为一个参数传入的话尽管内部是同步的,也会在多线程环境下在方法内出现脏读等现象。因为我觉得StringBuffer个别方法比如insert方法就不是线程安全的。
如果判断cs为String,则直接调用equals方法进行判断。
如果cs为其他CharSequence的实现类,则还要按照equals方法那样进行判断value的每个元素都相等