详述String类的equals方法
1、两个String类的对象采取直接赋值
ublic class Test {
public static void main(String[] args) {
String name1 = "Tom";
String name2 = "Tom";
System.out.println(name1 == name2);//常量池数据共享,name1和name2同时指向常量池里的“Tom”对象
System.out.println(name1.equals(name2));
}
}
程序运行结果中的第一个true是由语句“System.out.println(name1 == name2);” 得到的,逻辑运算符“==”比较的是两个变量所存对象的地址,因为变量“name1”和“name2”都采取直接赋值的方式,并且name1和name2都指向“Tom”对象,所以变量name1和name2指向常量池里的通一块地址,所以“name1==name2”运算结果是true。
方法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;
}
if (this == anObject) {
return true;
}
equals()方法中首先比较的也是方法调用者与参数中object对象的地址,如果两者地址相同,则返回true。因此“name1.equals(name2)”运行结果也是true。
2、两个String类对象一个直接赋值一个创建对象
public class Test {
public static void main(String[] args) {
String name1="Tom";
String name2=new String("Tom");
System.out.println(name1==name2);//false
System.out.println(name1.equals(name2));//思考:equals代码怎么执行的?
}
}
变量name1采取直接赋值的方式 ,所存对象的地址在常量池中,变量name2直接创建对象,所存对象的地址在堆中。变量name1和name2所存对象的地址显然是不一样,所以“name1==name2”的运算结果是false。
方法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;
}
private final char value[];
public String() {
this.value = "".value;
}
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
value[ ]是一个字符型数组,并且是一个全局变量。在执行String构造方法时,对value[ ]进行赋值。将字符串对象拆成一个个字符,存入字符数组value[ ]中。
本程序在执行equals方法时,方法调用者的地址和参数中object对象的地址显然是不一样的,因此执行第二个if语句。在第二个if语句中,先判断anObject变量指向的对象是否为String类,如果是,执行if语句。先把anObject变量所存对象下转型为String类型并存到新的变量anotherString中。然后通过字符数组value[ ],比较者两个字符串对象的长度和每个字符是否相同,如果相同则返回true.因为name1和name2指向的字符串对象都是“Tom”,所以equals方法的运行结果是true。
3、两个对象一个是String类型一个是其它引用类型
package equals;
public class Test {
public static void main(String[] args) {
String name="Tom";
Test test= new Test();
//System.out.println(name==test);//因为javac在编译时已经知道两个变量类型不相同,所以编译出错
System.out.println(name.equals(test));//思考: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;
}
变量name和test所存对象类型都不相同,两个对象的地址显然不同,因此equals()方法中第一个if语句不执行。Test类显然不是String类的子类,因此第二个if语句不执行,所以直接返回false。