【细节对比】Java中的 == 和 equal() 方法


前言

整理一下Java中的双等于号==和equal()对于不同的类型对比的究竟是什么


先来看看双等于号==

  • == 是一个Java的关系运算符,表示等价的意思,反之 != 表示不等价。
  • 如果基本类型要进行值比较那么只能用== 和 !=,而不能用equals()
  • == 和 !=当然也适合引用类型比较,但是比较的不是值,而是所指向的引用地址!(也可以理解成是否指向同一个对象)

再来看看equals()方法

  • 首先equals()方法是Object类下的方法,因此基本类型无法使用
  • equals()返回值是布尔类型。
  • 默认的情况下,比较的是对象的引用是否指向同一块内存地址。对象实例化时,即给对象分配内存空间,该内存空间的地址就是内存地址。使用方法如:dog.equals(dog2);

引用类型重写equals

  • 可以看到当equals传入引用对象Object的时候,使用==进行对比,对比的是引用地址。↓
  •   public boolean equals(Object obj) {
          return (this == obj);
      }
    
  • String类中对equals()方法进行重写↓
  •   public boolean equals(Object anObject) {
          if (this == anObject) {    先对比引用地址,如果相同直接返回true
              return true;
          }
          if (anObject instanceof String) {  如果引用地址不相同并且是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类型。。那么就直接返回false
      }
    
  • 再来看看Integer重写的equals方法
  • public boolean equals(Object obj) {
      if (obj instanceof Integer) {   如果是Integer类型
          return value == ((Integer)obj).intValue();    则对比值相不相等
      }
      return false;  不是Integer则返回false
     }
    
  • Charactor类型的重写,与Integer相似;Boolean和Long也是这样的
  •    public boolean equals(Object obj) {
          if (obj instanceof Character) {
              return value == ((Character)obj).charValue();
          }
          return false;
      }
    
  • Float类重写:有一些不同,会使用floatToIntBits方法,将Float的值转为单个精度浮点值的bit位,在进行对比;Double也类似不过用的是doubleToLongBits
  • public boolean equals(Object obj) {
      return (obj instanceof Float)
             && (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
    }
    
  • 当然这是对引用对象默认的情况下,这就是为什么要利用equals方法对比对象的时候,需要对对象的equals方法进行重写。(如下)

以Dog类为例,重写后的equals()方法如下(当然你可以根据自己想比较的属性来重写,这里我以age属性是否相同来重写equals()方法):

上面有四个判断,它们的含义分别是:

  • 1.判断地址是否相同----if (this == obj),相同则返回true
  • 2.经过1的判断,this不可能为null了,则判断形参对象是否为空----if (obj == null),为空则返回false
  • 3.getClass()可以得到Class模板类对象,判断类型是否一样-----if (getClass() != obj.getClass()),不一样则返回false
  • 4.判断属性值是否一样----if (age != other.age),不一样返回false
  • 5.如果地址相同,对象不为空,类型一样,属性值一样则返回true

equal()方法以及 hashCode()方法的关系?

  • 1、如果两个对象equals相等,那么这两个对象的HashCode一定也相同。
  • 2、如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置。
  • 3、所以重写了equals方法的话 也务必要将hashCode方法重写。(因为给equals方法加了逻辑,判断两个对象的属性相等也算是相等,那么hashCode也要兼容这个条件!即使地址不同~)【举个例子】

有个A类重写了equals方法,但是没有重写hashCode方法,看输出结果,对象a1和对象a2使用equals方法相等,按照上面的hashcode的用法,那么他们两个的hashcode肯定相等,但是这里由于没重写hashcode方法,他们两个hashcode并不一样,所以,我们在重写了equals方法后,尽量也重写了hashcode方法,通过一定的算法,使他们在equals相等时,也会有相同的hashcode值。


Object的equal()方法 和 == 双等于号的区别

  • equals 默认比较地址,但是包装类重写后会比较类型和内容, == 比较地址。

对于字符串👇
当我们想要比较两个字符串是否相同时,要特别注意,我们实际上是想比较字符串的内容是否相同。必须使用equals()方法而不能用==

String name1 = "123";
String name2 = "123";
System.out.println(name1 == name2);

输出true
这样为true只是因为第一次出现"123"的时候被放进了字符串常量,第二次就直接指向了这个"123"
但是当

String name1 = "abc";
String name2 = "ABC".toLowCase();这样的话
System.out.println(name1 == name2); 这里输出的就是false!!

输出false

解释
从表面上看,两个字符串用 == 和equals()比较都为true,但实际上那只是Java编译器在编译期,会自动把所有相同的字符串当作一个对象放入常量池,自然s1和s2的引用就是相同的。
所以,这种 == 比较返回true纯属巧合。换一种写法,==比较就会失败:


对于整数
==和equels()比较的含义
1.==是比较对象的内存地址,基本类型就是比较值
2.java对象的equals()方法都是继承Object.equals(Object o)方法的。比较的内容其实就是使用了“==”比较对象内存地址。

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

java8种基本类型包装器类和String类都重写了equals()方法,先比较类型在比较值,例如Long.equals(Object obj)

    public boolean equals(Object obj) {  //先对比类型,再对比值
           if (obj instanceof Long) {  
               return value == ((Long)obj).longValue();  
           }  
           return false;  
       }  

对于对象Object
== 是地址对比, equal()源码其实也是对比地址(也是通过==对比)


总结一下

1.基本类型只能使用 ==,不能使用equals,==对基本类型来说对比的是值,对引用类型对比的是引用地址
2.equals方法默认情况下(在Object类中)对比的是引用地址,但是到了不同的包装类型被重写了。
3.String的重写会先对比地址,然后判断是不是String类型,然后一个个字符进行对比
4.Integer、Charactor、Boolean、Long都是类似的,判断是不是对应类型,然后对比值
5.Float和Double都类似进行了转换,分别转换成了Int和Long的bits,然后进行值对比
6.我们自己创建的对象,当然也可以对应需求进行重写equals方法,对比如果地址不相等但是属性相等也返回true
7.equals方法重写了的话,别忘记把hashCode方法也重写了。。不然不同的对象equals返回true但是hashCode不同



————— END —————




  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值