Java中比较相等,有两种方法,各有不同,使用的地方也就不一样,这里我们分别探究一下:
==用来比较基本数据类型或者具有继承关系的引用类型,如果是基本类型,我们只关心值是不是一致(与数据类型无关),而如果是引用类型,我们比较的是两个对象是否指向的是同一个地址,看下面的实例:
class Per{
public String name;
public Per() {
}
public Per(String name) {
super();
this.name = name;
}
}
public class Test07 {
public static void main(String[] args) {
//基本数据类型
int i1 = 10;
int i2 = 11;
float f = 10f;
System.out.println(i1==i2);//false
System.out.println(i1==f);//true
//引用数据类型
Per p1 = new Per();
Per p2 = new Per();
Per p3 = p1;
System.out.println(p1==p2);//false
System.out.println(p1==p3);//true
//包装类
Integer in1 = 10;
Integer in2 = 10;
System.out.println(in1==in2);//true
Integer in3 = new Integer(10);
Integer in4 = new Integer(10);
System.out.println(in3==in4);//false
Double d = 10.0;
System.out.println(in1==i1);//true
// System.out.println(in1==d);//错的,没有直接的继承关系
}
}
由上面的代码可以证明上面的概念,这里面要注意一点,当包装类与之对应的基本类型相比值一样的时候,返回的是true,如果是包装类与包装类比较,那么如果使用new 赋值的是false,而使用=直接赋值的是true,这是因为我们直接用=赋值时会自动拆箱成基本类型比较,这样比较的值一致即可。
其实我们在一般的编程中使用的比较希望是值比较,不希望是地址比较,那么我们就可以使用equals()方法比较,但是equals()方法比较的时候,默认也不是进行值比较而是使用地址比较,这个我们要追溯到equals()在Object里的定义,因为equals()方法和toString()方法一样,如果不重写将使用Object里面定义的,那么先看一下Object里的equals方法的源码:
public boolean equals(Object obj) {
return (this == obj);
}
可以看出,Object中的equals方法也是调用了==来比较的,这样也是地址比较,但是我们来看看下面的代码:
String s1 = new String("a");
String s2 = new String("a");
System.out.println(s1.equals(s2));//true
两个引用类型的比较值也是true,这样就达到了值比较的目的,那么我们看看toString的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;
}
很明显是重写过了,那么在自己定义的类里面也可以重写equals()方法来实现我们需要的比较。
最后粘出对于String的equals方法的源码理解:
public boolean equals(Object anObject) {
//如果两个类的引用地址一样,说明是一个对象,肯定相等
if (this == anObject) {
return true;
}
//instanceof判断是否有继承关系,没有继承关系之间返回假
if (anObject instanceof String) {
String anotherString = (String) anObject;
//字符串在Java中是以字符数组存放的,value就是当前的字符数组
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;
}
/*
* 这种思想就是一步一步的排除不一样的情况,从大的方面判断到小的方法,一步步的排除,
* 一旦有为假的情况,直接返回假,退出,这样最大程度的减少判断
* 当然也不是一定非要排除错的情况,刚开始就判断了是不是真,最直接的目的是提高效率
* 尽量在少的判断下得出结论
*/