equals 和 == 的区别

引言:在理解equals和==的区别之前,必须先搞懂 栈和堆之间的区别
总的来说:
值类型是存储在内存中的栈中,而引用类型的变量在栈中存储的仅仅是引用类型变量的地址,而引用类型本身是存储在堆中。

equals 和 == 的区别:

  • == 操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
  • equals操作表示的是两个变量是否是对同一个对象的引用,即堆中的内容是否相同。
  • 更简单的说法:==比较的是地址,equals比较的是内容

例子:字符串的比较

public class EqualsTest {
    public static void main(String[] args){
        String s1 = "Test";
        String s2 = "Test";
        
        System.out.println("s1 == s2 : " + (s1 == s2));
        System.out.println("s1.equals(s2): " + s1.equals(s2));
    }
}

输出结果:
s1 == s2 : true
s1.equals(s2): true

接下来,做些改动:将s2通过new的方式来创建

public class EqualsTest {
    public static void main(String[] args){
        String s1 = "Test";
        String s2 = new String("Test");

        System.out.println("s1 == s2 : " + (s1 == s2));
        System.out.println("s1.equals(s2): " + s1.equals(s2));
    }
}

输出结果:
s1 == s2 : false
s1.equals(s2): true

我们发现这时候==操作结果为false了,equals方法依旧不变。

实际上,这是字符串缓冲池所起的作用。当我们在创建s1字符串后,s1便存放在字符串缓存池中。

  • 对于第一种情况,创建s2时,程序会在缓冲池中寻找到具有相同值的s1,因此s2和s1共同引用对象"Test"。也就是说s1和s2的引用地址相同,那么自然引用对象也是相同的咯。所以两者都为true。
  • 对于第二种情况,我们通过new方式创建了s2,相当于告诉程序“我要个新的,不要旧的”。因此,程序会重新创建一个"Test"对象在内存中,虽然它们的值相同,但它们的位置是不同的。因此,它们的引用地址自然是不同的,==操作自然为false,equals为true,因为它们的内容还是相同的。

当然,如果我们希望s2是从缓冲池中拿到对象,可以调用intern()方法实现:

public class EqualsTest {
    public static void main(String[] args){
        String s1 = "Test";
        String s2 = new String("Test").intern();

        System.out.println("s1 == s2 : " + (s1 == s2));
        System.out.println("s1.equals(s2): " + s1.equals(s2));
    }
}

输出结果:
s1 == s2 : true
s1.equals(s2): true

也就是说,通过intern()方法防止了程序创建重复的对象。


总结:

  • == 比较的是两个对象的地址,而equals比较的是两个对象的内容
  • 地址相同的两个对象自然内容也是相同的,即满足==为true,则equals必然为true。但注意对象内容相同的,地址不一定相同,因此,满足equals为true,但==不一定为true。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容