Java中“==“运算符与equals()的比较及hashCode()简单介绍


1. "=="与equals()的比较

== 运算符:

  1. 可以使用在基本数据类型和引用数据类型变量中
  • 比较基本数据类型变量,比较保存的实际是否相等 (类型不一定要相同)
  • 比较引用数据类型变量,比较两个对象的地址值是否相同,即两个引用是否指向同一个地址

使用:

int a = 10;
int b = 10;
double c = 10.0;
float d = 7;
System.out.println(a==b); // true
System.out.println(b==c); // true
System.out.println(c==d); // false

equals():

  • equals()是一个方法,而非运算符
  • 适用于引用数据类型
  • object中定义的equals方法和"=="的作用是相同的
  • String Date File 包装类等都重写了Object类中的equals方法。重写后,比较的是两个对象的实体内容是否相同。
  • 通常情况下,需要在自定义类中对equals方法进行重新操作去判断实体内容是否相同

自反性 :对于任何非空的参考值x , x.equals(x)应返回true 。

对称性 :对于任何非空引用值x和y , x.equals(y)应返回true当且仅当y.equals(x)回报true 。

传递性 :对于任何非空引用值x , y和z ,如果x.equals(y)回报true倍y.equals(z)的返回true ,然后x.equals(z)应该返回true 。

一致性 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false (前提是未修改在对象的equals比较中使用的信息)。

对于任何非空的参考值x , x.equals(null)应返回false 。

String str1 = "ABC123";
String str2 = "ABC123";
System.out.println(str1==str2); // true

equals()源码:

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

2. 重写equals()方法

首先,看一下不进行equals()重写的比较情况:

// 定义学生类,属性为姓名、年龄
class Student{
        private String name;
        private int age;

        public int getAge() {
                return age;
        }

        public void setAge(int age) {
                this.age = age;
        }

        public Student() {
        }

        public Student(String name, int age) {
                this.name = name;
                this.age = age;
        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }
}
Student stu1 = new Student("stu",18);
Student stu2 = new Student("stu",18);
System.out.println(stu1==stu2); // false
System.out.println(stu1.equals(stu2)); // false

stu1和stu2的姓名、年龄均相同,这时候"=="比较的是二者的地址值,为false;equals底层使用的也是这个运算符,所以也为false。

下面在Student类中对equals()进行重写:

重写方法由idea(Alt+Insert)自动生成,判断对象内容是否相等。

@Override
public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return Objects.equals(name, student.name);
}
//测试
Student stu1 = new Student("stu",18);
Student stu2 = new Student("stu",18);
System.out.println(stu1==stu2); // false
System.out.println(stu1.equals(stu2)); // true

注意点:

  • 重写equals()方法之后,为遵循相等的对象必须有相等的hashCode值,所以也要进一步对hashCode()进行重写。

3. hashCode()介绍

百科介绍:

hash code是一种编码方式,在Java中,每个对象都会有一个hashCode,Java可以通过这个hashcode来识别一个对象。至于hashcode的具体编码方式,比较复杂(事实上这个编码是可以由程序员通过继承和接口的实现重写的),可以参考数据结构书籍。而hashtable等结构,就是通过这个哈希实现快速查找键对象。这是他们的内部联系,但一般编程时无需了解这些,只要知道hashtable实现了一种无顺序的元素排列就可以了。.

注意点:

  1. 对象相等则hashCode一定相等;
  2. hashCode相等对象未必相等。

应用上述Student类举例:

  1. 在未重写hashCode()时,即使两个对象stu1和stu2的属性相同,因为他们的内存地址不同,所以产生的hashCode也不相同。

重写hashCode():

@Override
public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
}
  1. 当Student类对equals()进行重写后,为保证相等的对象必须有相等的hashCode值,因此也要对hashCode()进行重写,重新生成hashCode值。
//相等时,具有相同的hashCode值
System.out.println(stu1.hashCode()); // 3541086
System.out.println(stu2.hashCode()); // 3541086

注意: 当两个对象相等时,他们的hashCode一定相等;但当hashCode相等时,如果未重写hashCode(),那么hashCode相同即两对象指向了同一地址,但如果hashCode()重写后,hashCode相同两对象就未必会指向同一地址,因此,判断两个对象是否是指向同一地址,不能依靠类中的hashCode方法。

以上述Student类举例:

// 未重写hashCode()
Student stu1 = new Student("stu",18);
Student stu2 = new Student("stu",18);
Student stu3 = stu1;
System.out.println(stu1.hashCode()); // 1831932724  -->  指向同一地址
System.out.println(stu2.hashCode()); // 1747585824
System.out.println(stu3.hashCode()); // 1831932724  -->  指向同一地址
//用"=="判断是否为同一地址
System.out.println(stu1==stu2); // false
System.out.println(stu1==stu3); // true
//重写了hashCode()
Student stu1 = new Student("stu",18);
Student stu2 = new Student("stu",18);
Student stu3 = stu1;
System.out.println(stu1.hashCode()); // 3541086  -->  指向同一地址
System.out.println(stu2.hashCode()); // 3541086  -->  hashCode相同,地址不同
System.out.println(stu3.hashCode()); // 3541086  -->  指向同一地址
//用"=="判断是否为同一地址
System.out.println(stu1==stu2); // false
System.out.println(stu1==stu3); // true

如何获取对象的真实hashCode,而不受hashCode()方法被覆盖的影响?

public static int identityHashCode​( Object x)

无论给定对象的类是否覆盖hashCode(),都为给定对象返回与默认方法hashCode()返回的哈希码相同的哈希码。 空引用的哈希码为零。

举例:在hashCode相同下判断两对象是否指向同一地址:

Student stu1 = new Student("stu",18);
Student stu2 = new Student("stu",18);
System.out.println(stu1.hashCode()); // 3541086
System.out.println(stu2.hashCode()); // 3541086
System.out.println(System.identityHashCode(stu1)); // 1831932724
System.out.println(System.identityHashCode(stu2)); // 1747585824
System.out.println(stu1==stu2); // false

——————END-2022-06-18——————

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苡荏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值