【千字详解】==与equals的区别

目录

1、介绍

2、JVM的内存分配

3、两者的主要区别

4、总结:


1、介绍

        ==与equals是两个我们在编写程序的时候经常用到的语句,也是面试中经常遇到的问题,本文将详细介绍==与equals,旨在帮大家完全弄懂==与equals之间的区别。

2、JVM的内存分配

        在JVM中,内存分为堆内存跟栈内存。他们二者的区别是: 当我们创建一个对象(new Object)时,会调用对象的构造函数来开辟空间,将对象数据存储到堆内存中,与此同时在栈内存中生成对应的引用,当我们在后续代码中调用的时候用的都是栈内存中的引用。值得注意的是,基本数据类型是存储在栈内存中。

3、两者的主要区别

  • == 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
  • equals大多时候用来比较的是两个对象的内容是否相等。
  • equals 是方法,是可以被重写的,而 == 属于操作符;

      equals源码:由此可知,equals底层还是由==来实现的,如果没有对equals进行重写,比较的还是它们在(栈)内存中的地址

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

下面通过几个简单的例子,进一步说明 :

    String a = "Hello World";
    String b = new String("Hello World");
    String c = b;              
    System.out.println("a == b:" + a == b);             //false
    System.out.println("b == c:" + b == c);             //true
    System.out.println("a == c:" + a == c);             //false
    System.out.println("a.equals(b):" + a.equals(b));   //true
    System.out.println("b.equals(c):" + b.equals(c));   //true
    System.out.println("a.equals(c):" + a.equals(c));   //true

    最终的打印会是:
    a == b:false
    b == c:true
    a == c:false
    a.equals(b):true
    b.equals(c):true
    a.equals(c):true

对于引用类型的变量来说(例如 String 类)才有 equals 方法,因为 String 继承了 Object 类, equals 是 Object 类的通用方法。对于该类型对象的比较,默认情况下,也就是没有复写 Object 类的 equals 方法,使用 == 和 equals 比较是一样效果的,都是比较的是它们在内存中的存放地址。但是对于某些类来说,为了满足自身业务需求,可能存在 equals 方法被复写的情况,这时使用 equals 方法比较需要看具体的情况,例如 String 类,使用 equals 方法会比较它们的值

        String类中重写之后的equals方法源码:

public boolean equals(Object other) {
  if (other == this) {
    return true;
  }
  if (other instanceof String) {
      String s = (String)other;
      int count = this.count;
      if (s.count != count) {
          return false;
      }
      if (hashCode() != s.hashCode()) {
          return false;
      }
      char[] value1 = value;
      int offset1 = offset;
      char[] value2 = s.value;
      int offset2 = s.offset;
      for (int end = offset1 + count; offset1 < end; ) {
          if (value1[offset1] != value2[offset2]) {
              return false;
          }
          offset1++;
          offset2++;
      }
      return true;
  } else {
      return false;
  }
}

 对于基本类型的变量来说(如 short、 int、 long、 float、 double),只能使用 == ,因为这些基本类型的变量没有 equals 方法。对于基本类型变量的比较,使用 == 比较, 一般比较的是它们的值

下面通过一个特殊例子,可以进一步了解:

public class Test {
    public static void main(String[] args) {
        Integer i1 = 10;
        Integer i2 = 10;
        System.out.println(i1 == i2); // true

        Integer i3 = 128;
        Integer i4 = 128;
        System.out.println(i3 == i4); // false
    }
}

此时前者== 返回 true

那么为什么 i3 和 i4 是返回 false 呢?

这是因为Integer对象有一个常量池,其值的范围是-128到127。当对Integer对象进行比较的时候,如果数值在-128——127以内,会直接从常量池中调用,在使用“= =”进行比较内存地址的时候,他们是相等的。但是当interger包装的数值不在常量池范围内,integer会重新new一个Integer对象,这个时候,使用”= =“进行比较就是false

4、总结:

1、==用来比较两者的栈内存地址

2、equals底层还是==,它会比较两者的栈内存地址,但是如果对它进行重写的话,需要看情况而定,例如Sting类中的equals,它不仅会比较栈内存地址,而且如果内存地址不相等,还会比较两者的内容

3、特殊情况,Integer这样的对象,它会一个常量池。
 

猜你喜欢

转载自blog.csdn.net/HouGOD/article/details/123844395