本文共 9723 字,大约阅读时间需要 32 分钟。
一、先说最简单的 == 吧
==用于判定左右两边成员的"数值"是否相等
1、等号两边是基本类型及其包装类时,内容一致返回true。
2、等号两边是字符串时,字符串的内容相同返回true。
3、等号两边是对象时,若为同一对象(在内存中的地址相同)则返回true。
import java.util.ArrayList;public class Main{ public static void main(String[] args) { int a=1,b=1; System.out.println("a==b:"+(a==b)); double c=0.1,d=0.1; System.out.println("c==d:"+(c==d)); boolean b1=true,b2=true; System.out.println("b1==b2:"+(b1==b2)); char char1='x',char2='x'; System.out.println("char1==char2:"+(char1==char2)); String s1="abc",s2="abc"; System.out.println("s1==s2:"+(s1==s2)); ArrayListarrayList1=new ArrayList<>(); ArrayList arrayList2=(ArrayList ) arrayList1.clone(); System.out.println("arrayList1==arrayList2:"+(arrayList1==arrayList2)); Car car1=new Car("奔驰"); Car car2=new Car("奔驰"); System.out.println("car1==car2:"+(car1==car2)); Integer integer1=1,integer2=1; System.out.println("integer1==integer2:"+(integer1==integer2)); Character character1='x',character2='x'; System.out.println("character1==character2:"+(character1==character2)); }}
结果:
二、hashCode方法:(注意:Object类的后代都有hashCode方法,"abc"这样的String也算,基本类型(不含包装类)无hashCode方法)
hashCode是Object类中的方法,其他类都继承了这一方法。
1、如果hashCode方法被重写,则遵循重写后的规则
在JDK中,String类就重写了hashCode方法,如下:
补充1:
补充2:
从上面这个规则我们可以得知,如果两个String的内容一样,则二者的hashCode相同。
示例:
a、代码public class Main{ public static void main(String[] args) { String s1="abc",s2="abc"; System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); }}b、结果9635496354
示例:String重写后的hashCode方法并不十分高明!
a、代码 String a="重地",b="通话"; System.out.println(a.hashCode()); System.out.println(b.hashCode());b、结果:撞车了!11793951179395
2、如果hashCode方法没有被重写,那么hashCode由系统根据一定的算法生成,相同对象(物理地址相同)的hashCode相同,不同对象的hashCode也有可能相同。
a、代码 Integer[] array={1,2,3}; Integer[] array_copy=array.clone(); Integer[] ref_copy=array; System.out.println("array:"+array.hashCode()); System.out.println("array_copy:"+array_copy.hashCode()); System.out.println("ref_copy:"+ref_copy.hashCode());b、结果array:1163157884array_copy:1956725890ref_copy:1163157884
三、toString方法
1、如果没有被重写,则遵循Object中的实现:
即:类的全路径名@16进制hashCode
示例:
a、代码 Car car=new Car("BMW"); System.out.println(car.toString()); System.out.println(car); //与上行等效b、结果cn.edu.nenu.Car@4554617ccn.edu.nenu.Car@4554617c
2、如果toString方法被重写,则遵循重写后的规则
JDK中Collection(当然也包括它的所有子类)就重写了toString方法:
a、代码 Collectioncollection=new ArrayList<>(); collection.add(1); collection.add(2); System.out.println(collection.toString()); System.out.println(collection);b、结果[1, 2][1, 2]
四、equals方法(注意:Object类的后代都有equals方法,"abc"这样的String也算,基本类型(不含包装类)无equals方法)
1、Object中的equals方法:
从上面可以看出,如果【一个类】没有重写equals方法,那么它的equals方法和==作用相同。
2、如果重写了equals方法,则遵循重写后的规则
JDK中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; }
代码大意:内容相同即相等。
当然,包装类也都重写了equals方法。
3、Objects工具类中的equals方法
五、Objects工具类中的deepEquals方法
Objects.java中的deepEquals方法:
调用了Arrays.java中的deepEquals0方法:
static boolean deepEquals0(Object e1, Object e2) { assert e1 != null; boolean eq; if (e1 instanceof Object[] && e2 instanceof Object[]) eq = deepEquals ((Object[]) e1, (Object[]) e2); else if (e1 instanceof byte[] && e2 instanceof byte[]) eq = equals((byte[]) e1, (byte[]) e2); else if (e1 instanceof short[] && e2 instanceof short[]) eq = equals((short[]) e1, (short[]) e2); else if (e1 instanceof int[] && e2 instanceof int[]) eq = equals((int[]) e1, (int[]) e2); else if (e1 instanceof long[] && e2 instanceof long[]) eq = equals((long[]) e1, (long[]) e2); else if (e1 instanceof char[] && e2 instanceof char[]) eq = equals((char[]) e1, (char[]) e2); else if (e1 instanceof float[] && e2 instanceof float[]) eq = equals((float[]) e1, (float[]) e2); else if (e1 instanceof double[] && e2 instanceof double[]) eq = equals((double[]) e1, (double[]) e2); else if (e1 instanceof boolean[] && e2 instanceof boolean[]) eq = equals((boolean[]) e1, (boolean[]) e2); else eq = e1.equals(e2); return eq; }
Arrays.java中的deepEquals方法:
public static boolean deepEquals(Object[] a1, Object[] a2) { if (a1 == a2) return true; if (a1 == null || a2==null) return false; int length = a1.length; if (a2.length != length) return false; for (int i = 0; i < length; i++) { Object e1 = a1[i]; Object e2 = a2[i]; if (e1 == e2) continue; if (e1 == null) return false; // Figure out whether the two elements are equal boolean eq = deepEquals0(e1, e2); if (!eq) return false; } return true; }
Arrays.java中的euqals方法:以boolean[]为例
public static boolean equals(byte[] a, byte[] a2) { if (a==a2) return true; if (a==null || a2==null) return false; int length = a.length; if (a2.length != length) return false; for (int i=0; i
上面涉及的代码比较多,大意就是:
a、如果deepEquals(Object a, Object b)中的a和b是两个数组对象,对每一个索引,用==(如果元素是对象,也会使用equals)作用于两个数组的对应元素,全通过返回true;
b、如果deepEquals(Object a, Object b)中的a和b是两个非数组,==为true或者对象的equals为true则返回true。
六、对象自己的equals方法和Objects工具类中的equals方法
1、作用几乎一样,不同的是对象的equals方法要求调用equals方法的对象非空,否则会抛出空指针异常;而Objects工具类中的equals方法更安全,不用担心空指针异常的事。
2、联系
从上面Objects的equals方法实现来看,【Objects工具类中的equals方法】是【对象自己的equals方法】的安全版,仅此而已。
七、equals方法与deepEquals方法
1、如果只是非数组【对象】,二者等价。
a、代码public class Main { public static void main(String[] args) { String str1="abc",str2="abc"; System.out.println("str1.equals(str2):"+str1.equals(str2)); System.out.println("Objects.deepEquals(str1,str2):"+Objects.deepEquals(str1,str2)); Car car1=new Car("BMW"); Car car2=new Car("BMW"); System.out.println("car1.equals(car2):"+car1.equals(car2)); System.out.println("Objects.deepEquals(car1,car2):"+Objects.deepEquals(car1,car2)); }}b、结果str1.equals(str2):trueObjects.deepEquals(str1,str2):truecar1.equals(car2):falseObjects.deepEquals(car1,car2):false
2、如果是基本类型的数组,equals在二者物理地址相同(即实际上是同一个数组)的情况下返回true。如果物理地址不同,就算内容一样,也会返回false,不好不好。而deepEquals只需内容一样就会返回true。
a、代码public class Main { public static void main(String[] args) { int[] array={1,2,3}; int[] array_ref=array; //与array其实是同一个数组,二者物理地址相同 int[] array_same_content={1,2,3}; //与array为两个数组,物理地址不同,但内容相同 System.out.println("array.equals(array_same_content):"+array.equals(array_same_content)); System.out.println("Objects.equals(array,array_same_content):"+Objects.equals(array,array_same_content)); System.out.println("Objects.deepEquals(array,array_same_content):"+Objects.deepEquals(array,array_same_content)); System.out.println("array.equals(array_ref):"+array.equals(array_ref)); System.out.println("Objects.deepEquals(array,array_ref):"+Objects.deepEquals(array,array_ref)); }}b、结果array.equals(array_same_content):falseObjects.equals(array,array_same_content):falseObjects.deepEquals(array,array_same_content):truearray.equals(array_ref):trueObjects.deepEquals(array,array_ref):true
3、如果是对象类型的数组,equals在二者物理地址相同(即实际上是同一个数组)的情况下返回true。如果物理地址不同,就算内容一样,也会返回false,不好不好。而deepEquals则不会这么苛刻,它会进一步去比较每个元素,又是比较。。。对元素怎么比较呢?也是deepEquals。。。(可能有多层嵌套,所以叫deepEquals嘛)。还是用案例说话吧!
数组中的对象成员重写了equals方法(内容相同即相等):
a、代码public class Main { public static void main(String[] args) { String[] strArray={"Tom","Mary"}; //String[]数组的成员是String对象,String对象重写了equals方法(内容相同即相等) String[] strArray_same_content={"Tom","Mary"}; System.out.println(strArray.equals(strArray_same_content)); //物理地址不同,false System.out.println(Objects.deepEquals(strArray,strArray_same_content)); //内容相同,每个String成员的equals为true,最后返回true }}b、结果falsetrue
数组中的对象成员没有重写equals方法(即要想每个成员的equals为true,成员的物理地址得相同!)
示例1:public class Main { public static void main(String[] args) { Car[] array=new Car[]{new Car("奔驰"),new Car("宝马")}; //Car[]中的Car没有重写equals方法,两个Car元素要想equals,物理地址相同才行! Car[] array_same_content_for_each_element=new Car[]{new Car("奔驰"),new Car("宝马")}; System.out.println(array.equals(array_same_content_for_each_element)); System.out.println(Objects.deepEquals(array,array_same_content_for_each_element)); }}结果:falsefalse示例2:public class Main { public static void main(String[] args) { Car BMW=new Car("BMW"),Benz=new Car("Benz"); Car[] array=new Car[]{BMW,Benz}; Car[] array_same_address_for_each_element=new Car[]{BMW,Benz}; System.out.println(array.equals(array_same_address_for_each_element)); //两个数组物理地址不同,false! System.out.println(Objects.deepEquals(array,array_same_address_for_each_element)); //虽然两个数组的物理地址不同,但每个元素地址都相同,true! }}结果:falsetrue
更复杂的情况就不分析了。
八、deepEquals有什么用?
当我们想要比较两个数组内容是否相同时,就用deepEquals!(若为对象数组,且对象没有重写equals方法,则不推荐使用)
转载地址:https://liuxingchang.blog.csdn.net/article/details/109438335 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!