JAVA:==与equals的区别

本文详细探讨了JAVA中`==`与`equals()`的区别。`==`用于判断基本类型时比较值,引用类型时比较地址。而`equals()`在未重写时与`==`相似,但在如String等类中重写后会比较内容。通过分析源码,解释了当对象引用不同但内容相同时,重写后的`equals()`会返回`true`。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,==的理解

①,既可以判断基本类型,又可以判断引用类型

②,如果判断基本类型,判断的是值是否相等,例如:int i=10,double d=10.0

③,如果判断的是引用类型,判断的是地址是否相等,即判定是不是同一个对象。

例如源代码:

package com.whpu.equals_;
public class equals_1 {
    public static void main(String[] args){
        int i=10;
        double d=10.0;
        System.out.println(i==d);
        B b=new B();
        B a=b;
        System.out.println(a==b);
    }
}
    class A{}
    class B{}

第一个比较的是基本类型,值得注意的是,10和10.0它们的值是相同的,虽然数据类型不一样。

第二个比较的是引用类型,创建两个B类对象,分别用b和a引用对象名去指向这个B对象,所以这个时候比较的是地址,a和b指向的地址是同一个地方,所以比较结果是相同的。

二,equals的理解

重点来了!!!

用equals去比较两个数是不是相等的分两类,第一类,这两个变量类型不对equals中的方法造成重写,比如我们自己命名的Student类名,就是不构成重写的,这个时候用这个stu变量去引用equals方法时,调用的是Object中的equals方法,只比较地址是不是一样的,而不比较内容是不是一样的。例如下图源代码:

 

 因为每new一个student,就会在堆区中创建一个新对象,它new了两个Student,所以就会在堆内创建两个Student对象,分别用stu1和stu2去指向。很显然,它们的地址是不一样的,而且在Student方法中是没有equals方法的,所以也不存在造成equals方法的重写,直接调用的就是Object中的equals方法。比较地址是不是一样的,如果不一样,则返回false,一样则返回true。题目中是返回false的。

下面提供

Object中的equals方法

public boolean equals(Object obj){

return(this == obj);       //用==判断地址一不一致,不一致则为false,返回,否则返回true。

}

就短短的三行。

第二种情况,如果我们要比较的两个变量它们的类型例如String中有equals方法的重写,那么调用这个equals方法时,先执行运行类型的变量类型中的equals方法,而这个重写的变量类型的方法中,它和Object中的equals方法是不大一样的,它在原来Object中的equals的基础上新加了一个用来判断内容是否一样的if语句,也就是说,如果这两个比较的变量即使它们的地址是不一样的,只要它们的内容是一样的,也被认为是true的。

下面提供一个String类中equals的方法。

String类中equals源代码

public boolean equals(Object anObject) {
    // 第一个if,判断两者是否是同一个内存地址
    if (this == anObject) {
        return true;
    }
    // 第二个if,判断两者的值是否相同(将每个字符逐一比较)
    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;
}

 

 如上面两张图,分别在堆中创建两个String对象,对象内都有hello内容,显然,这两个对象用u1和u2指向的地址是不一样的,一个指向的是u1的实例对象,一个指向的是u2的实例对象,但是由于String类型它调用equals方法时,造成了equals方法的重写,所以系统就首先会考虑调用运行类型的String类中的equals方法,而不会首先考虑编译类型中的Object中的方法。来到了String中的equals方法中,也就是上面三张图的第一张,有String类中equals的原码,第一步还是比较地址是不是一样的,很显然,u1和u2分别指向两个不同的String实例对象,所以地址是不一样的,因此第一个if语句不会被调用。接着往下,到第二个if语句,因为Object是所有类的超类,所以可以用到对象的多态,用Object anObject去接收一个String u2类,接收了之后,anObject就是父类的引用指向子类的对象String类了,构成一个向上转型,接着第二个if语句的意思就是这个父类的引用anObject它的运行类型是不是String类型,很显然是,因为前面我们用Object anObject去接收String u2,所以编译类型是Object,运行类型是String,所以第二个if语句通过。接着就来一波向下转型的操作,因为后面是想调用String类中的特有属性的值,而anObject作为父类的引用,只能调用到子类中父类有的方法,而不能调用父类没有的方法或属性,所以必须将原来的anObject父类的引用向下转型为子类,也就是String anotherString=(String) anObject,这样,就可以使用anotherString来调用这个特有的属性值了,后面的步骤就是比较两个值的内容是否相同,通过拆分数组比较的方法,最终两个相同的hello显然是相同的,所以返回true。

三,总结

==比较方法很简单,主要是equals方法,要考虑重写,如果子类类型没有重写,则直接调用Object中的equals方法,单纯的比较两个变量地址是否一样,如果子类类型有重写,因为我们知道,看equals的原码都是使用Object anObject去接收对象的,所以Object总是为编译类型,而子类类型总是运行类型,所以如果有重写equals方法,首先考虑采用的是运行类型的equals方法,也就是String中的equals方法,而这个子类的equals方法在原来Object中的equals方法的基础上新加了一个if语句用来判断对象中的内容是否相等,所以即使两个变量的地址不一样,只要它们的内容是一样的,还是会返回true的,这就是equals方法的主要区别。不懂就看equals在Object和子类重写方法中的原码,自己多看看,分析分析!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值