#equals、deepEquals、==、hashCode()、toString() @FDDLC
发布日期:2021-06-30 20:58:23 浏览次数:3 分类:技术文章

本文共 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));        ArrayList
arrayList1=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、代码        Collection
collection=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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:#Java队列:Queue @FDDLC
下一篇:#DeepClone、Clone #深复制、浅复制 #深拷贝、浅拷贝 @FDDLC

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月08日 14时25分11秒