深入解析==与equals()区别

时间:2022-07-25
本文章向大家介绍深入解析==与equals()区别,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本文源自 公-众-号 IT老哥 的分享

IT老哥,一个在大厂做高级Java开发的程序员,每天分享技术干货文章

前言

相信大家一定在很多地方多看到过==equals()的区别,也把区别讲的很详细,每次记住了,很快又会变得模糊不清。 这时就需要从原理深入剖析,一招制敌!

认识==的用法

在Java中,==的作用有两个

(1).基础数据类型:比较的是两者的值是否相等,比如int,float,double变量。

public static void main(String[] args) {
  int a = 1;
  int b = 1;
  float x = 3.2f;
  float y = 3.2f;
  System.out.println(a == b); 
  System.out.println(x == y); 
 }

此时结果,两个都为true。

(2).引用数据类型:比较的是两者的地址是否相同,比如Integer等。String是一个特殊的,后面再讨论。

public static void main(String[] args) {
  Integer a = new Integer(1);
  Integer b = new Integer(1);
  Integer c = 1;
  System.out.println(a == b); 
  System.out.println(a == c); 
 }

此时结果,两个都为false。因为使用Integer类,每次都创建了新的对象,所以分配的地址是不同的。但Integer类与int作比较结果如何呢?

public static void main(String[] args) {
  Integer a = new Integer(1);
  Integer b = new Integer(1);
  int c = 1;
  System.out.println(a == b);//false
  System.out.println(c == a);//true
  System.out.println(c == b);//true
 }

输出结果:false,true,true。此时我们不难发现,当包装类与其基本类型进行比较时,会转变为对两者的值的比较。

认识equals()的用法

equals()方法源自Object类,先看一下源码是什么样:

public boolean equals(Object obj) {
        return (this == obj);
    }

看到这里,很快就发现equals()方法和==是相同的,所以在使用基本数据类型和引用对象(包装类除外)比较时,两者不存在区别。

public static void main(String[] args) {
  Integer a = new Integer(1);
  Integer b = new Integer(1);
  int c = 1;
  System.out.println(a.equals(c)); 
  System.out.println(b.equals(c)); 
 }

此时结果为:true,true。当包装类与其基本类型用equals()方法进行比较时,同样比较两者的值,也不存在区别。

不同点

有一点是比较特殊的,在使用equals()方法对包装类和包装类进行比较时,则会不同。

public static void main(String[] args) {
  Integer a = new Integer(1);
  Integer b = new Integer(1);
  System.out.println(a.equals(b));//true
  System.out.println(a == b); //false
 }

输出结果:true,false。包装类和包装类采用equals()方法,也会转变成对值得比较。为什么呢?因为包装类重写了Object类的equals()方法。打开重写后equals()方法的源码:

public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

从这里可以看出,包装类和包装类的比较,就是两者值得比较。

String类中的==和equals()方法

在String中,重写了Object类的equals(),自然逻辑和功能不同了。

String类中的equals()方法

先来看看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;
}

在源码第一个判断中,若两个对象指向地址相同,则返回true。第二个判断中,若字符内容相同,则返回true。其实就是对两者值得比较。

public static void main(String[] args) {
  String a = "Hello";
  String b = "Hello";
  System.out.println(a.equals(b));//true
}

输出结果:true。

String类中的测试

public static void main(String[] args) {
  String a = "Hello";
  String b = "Hello";
  String c = new String("Hello");
  String d = c;
  System.out.println(a == b);//true
  System.out.println(a == c);//false
  System.out.println(c == d);//true

  System.out.println(a.equals(b));//true
  System.out.println(a.equals(c));//true
  System.out.println(c.equals(d));//true
}

为什么出现这样的结果。可以从内存的角度来解释:

3.通过内存来解释

在Java中,一般是把对象放在堆区,对象的引用则放在了栈区

从上图可以看出:

  • 当String a = “Hello”;创建一个引用类型a,指向堆区一个位置,用于保存字符串对象;
  • 当String b = “Hello”;java会到它的常量池中"hello"是不是在常量池中已存在。如果已经存在则返回这个常量池中的"hello"的地址(在java中叫引用)给变量b;
  • String c= new String(“hello world”); 会在堆区再次存放一个字符串对象;
  • String d = c;当中d和c是相同的引用,指向同一个地址。

所以根据此可以判断以上输出结果:

云服务器云硬盘数据库(包括MySQL、Redis、MongoDB、SQL Server),CDN流量包,短信流量包,cos资源包,消息队列ckafka,点播资源包,实时音视频套餐,网站管家(WAF),大禹BGP高防(包含高防包及高防IP),云解析SSL证书,手游安全MTP移动应用安全云直播等等。

//true 指向同一个地址
System.out.println(a == b);  

//false 指向不同地址  
System.out.println(a == c);

//true 指向同一个地址
System.out.println(c == d);

//true 地址指向的内容相同  
System.out.println(a.equals(b));

//true 地址指向的内容相同  
System.out.println(a.equals©);

//true 地址指向的内容相同
System.out.println(c.equals(d));