不管在平时的开发中还是在我们面试的过程中,我们常常用到equals() 和 == ,但两者又有什么区别呢,网上的文章千篇一律,有用的文章万里挑一,看到很多文章说的很对,但又不是很完整,只是阐述了其中的某一个点而已,故作一小结,用最通俗的话记最直白的点。
equals()和 == 的区别
equals | == |
---|---|
equals是一个方法 | ==是一个运算符 |
equals()指的是值是否相同 | ==指引用是否相同 |
equals()是对字符串(引用类型)的内容进行比较 | ==是指对(基本数据类型)内存地址进行比较 |
看Object源码
java.lang.Object:equals初始比较方法
public boolean equals(Object obj) {
//返回内存中的存发地址,比较结果相同为true,否则为false
return (this == obj);
}
注:JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址
从Object类不难看出,本质上 equals 上还是 ==
equals
实际上就是比较判断两个变量或者实例指向同一个内存空间的值是不是相同
==
是判断两个变量或者实例是不是指向同一个内存空间
从源码得知,equals方法进来先进行==的判断,我们就可以理解为
==
是判断两个人是不是住在同一地址(判断的是地址)
而equals
是判断同一地址里住的人是不是同一个人(判断的是内容)
java.lang.String的equals()方法
public boolean equals(Object anObject) {
//首先看一下是不是比较同一个对象(其实比较的是两个对象的内存地址),如果是直接返回true
if (this == anObject) {
return true;
}
// instanceof 判断anObject是否为String的一个实例,如果不是直接返回false
//如果是再进一步判断两个字符串是否相等:将字符串转化为char数组进行一一比较
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;
}
java.util.Arrays的equals()方法
public static boolean equals(int[] a, int[] a2) {
//两个数组为同一对象的内存地址是否相同返回true
if (a==a2)
return true;
//两个数组全为null返回false
if (a==null || a2==null)
return false;
//两个数组长度不一返回false
int length = a.length;
if (a2.length != length)
return false;
//两个数组不是同一对象,不为null且长度相等再比较数组的每一个元素是否都相等
for (int i=0; i<length; i++)
if (a[i] != a2[i])
return false;
return true;
}
java.util.Objects的equals()方法
public static boolean equals(Object a, Object b) {
//如果a,b都为null返回true,如果只有一个为null返回false,否则返回a.equals(b)的结果
return (a == b) || (a != null && a.equals(b));
}
java.util.Date的equals()方法
public boolean equals(Object obj) {
//obj必须是Date类型,在把两个时间转化为从GMT 1970-01-01 00:00:00到此date对象上时间的毫秒数进行比较
return obj instanceof Date && getTime() == ((Date) obj).getTime();
}
注:
在一些类库当中这个方法equals()方法被覆盖掉了(所有的类都继承于Object类),如上面的String,Arrays,Date,在这些类改变了当中equals有其自身的实现,此时,如果用equals()的话就回调用子类对象里面的方法,而不再是比较类在堆内存中的存放地址了,所以说只有重写equals()方法后,两者比较的才是内容.或者说重写可以使自己定义比较的规则,不想按照地址去比较.
下面用Demo
来分析一波:
public static void main(String[] args) {
String str0 = new String();
String str1 = new String();
System.out.println(str0.equals(str1));// true 比较物理地址和值
System.out.println(str0 == str1);//false
//如果想要equals方法比较为true,必须重写hashcode方法 String类默认已重写
System.out.println(str0.toString().equals(str1.toString()));//true
//两个不同的内存地址,两个不同的对象
System.out.println(str0.toString()==str1.toString());//false
String s1 = new String("123");
String s2 = new String("123");
System.out.println(s1.equals(s2)); // true 比较物理地址和值
System.out.println(s1 == s2); //false
//如果想要equals方法比较为true,必须重写hashcode方法 String类默认已重写
System.out.println(s1.toString().equals(s2.toString()));//true
//两个不同的内存地址,两个不同的对象
System.out.println(s1.toString()==s2.toString());//false
}
在String中 equals方法被重写 当物理地址不同时,会进一步比较值,代码如下:
if(object instanceof String){}
public static void main(String[] args) {
//两个类型相同的类比较
Student sdt1 = new Student();
Student sdt2 = new Student();
System.out.println(sdt1.equals(sdt2));//false
System.out.println(sdt1 == sdt2);//false
System.out.println(sdt1.toString().equals(sdt2.toString()));//false
}
两者比较的不是对象中字段的值或者说本身对象的值,而比较的是物理地址。
**如果要保证sdt1.toString().equals(sdt2.toString())
为true,那么就要重写hashcode方法了
在java中 首先比较的就是hashcode。可以这样:
右键:
public static void main(String[] args) {
/**
* 对于基本类型的变量,==和equals的区别
*/
int t1=57;
int t2=67;
int t3=124;
int t4=124;
/**
* ==对于基本数据类型,判断两个变量的值是否相等
*/
System.out.println(t1==t2);//false
System.out.println((t1+t2)==t3);//true
System.out.println(t3==t4);//true
/**
* equals 不能用于基本数据类型。只能用于类变量。对于基本数据类型要用其包装类
*/
Integer i1=new Integer(t1);
Integer i2=new Integer(t2);
Integer i3=new Integer(t3);
Integer i4=new Integer(t4);
System.out.println(i1.equals(i2));//false
System.out.println(i3.equals(i1+i2));//true
System.out.println(i3.equals(i4));//true
/**
* 对于对象变量,==和equal的区别
*/
String st1="I ";
String st2="is man";
String st3="I is man";
String st4="I is man";
System.out.println(st1==st2);//false
System.out.println((st1+st2)==st3);//false
System.out.println(st3==st4);//true
/**
* 因为对象变量的存储的是对象在内存中的路径,即内存地址。所以用“==”比较时,即使
* 对象的值相等,但是他们的内存地址不同,所以==的结果为false。故“==”用于比较两
* 个变量的值是否相等,而不是变量引用的对象是否相等
*/
System.out.println(st1.equals(st2));//false
System.out.println((st1+st2).equals(st3));//true
System.out.println(st3.equals(st4));//true
/**
* equal用于比较两个对象是否相同
*/
}