一文详解java中的==和equals()

一文详解java中的==和equals()一文详解 运算符和 equals 方法 java 和 equals

大家好,欢迎来到IT知识分享网。

目录

一、”==”运算符

二、”equals()”方法

三、举例说明和解释

3.1、例子

3.2、基本数据类型的比较

3.3、引用数据类型的比较

    3.3.1 String类

    3.3.2 未重写equals方法的类

四、为什么重写equals方法就一定要重写hashCode方法 

4.1 为什么要重写equals方法

4.2 hashCode

4.3 为什么equas和hashCode要一起重写?

        4.3.1 Set集合正常使用

        4.3.2  Set集合的”异常”使用

4.4 原因分析 

4.5 总结

五、练手举例


“==”和equals 最大的区别是
    1.”==”是运算符,如果是基本数据类型,则比较存储的值;如果是引用数据类型,则比较所指向对象的地址值。
    2.equals是Object的方法,比较的是所指向的对象的地址值,一般情况下,重写之后比较的是对象的值。

一、”==”运算符

   1.如果比较的对象是基本数据类型,则比较的是其存储的值是否相等;

   2.如果比较的是引用数据类型,则比较的是所指向对象的地址值是否相等(是否是同一个对象)。

二、”equals()”方法

        equals是Object的方法,用来比较两个对象的地址值是否相等。

        方法如下:

注意:
equals 方法不能用于比较基本数据类型,如果没有对 equals 方法进行重写,则相当于“==”,比较的是引用类型的变
所指向的对象的地址值。 

    一般情况下,类会重写equals方法用来比较两个对象的内容是否相等。比如String类中的equals()是被重写了,比较的是对象的值

三、举例说明和解释
3.1、例子
3.2、基本数据类型的比较

“==”正常比较其值。equals不用于基本数据类型的比较。

3.3、引用数据类型的比较
    3.3.1 String类

     String类对equals()方法进行了重写。

     1.创建字符串对象一般有如下两种写法:

      •  对于String s2 = new String(“world”);
            首先在堆内存中申请内存存储String类型的对象,将地址值赋给s2;
            在方法区的常量池中找,有无world:
            若没有,则在常量池中开辟空间存储world,并将该空间的地址值赋给堆中存储对象的空间;
            若有,则直接将world所在空间的地址值给堆中存储对象的空间。



      •  对于String s1 = “hello”;
            在方法区的常量池中找,有无hello,如果没有,就在常量池中开辟空间存储hello。
            然后只需要将hello所在空间的地址值赋给 s1。

字符串作为最基础的数据类型,使用非常频繁,如果每次都通过 new 关键字进行创建,会耗费高昂的时间和空间代价。Java 虚拟机为了提高性能和减少内存开销,就设计了字符串常量池. 在JDK1.7之前字符串常量池是存储在方法区的。JDK1.7之后存储在堆中了。

      2.String类对equals的重写如下:

代码解释

       • 若当前对象和比较的对象是同一个对象,即return true。也就是Object中的equals方法。
       • 若当前传入的对象是String类型,则比较两个字符串的长度,即value.length的长度。
       • 若长度不相同,则return false。
       • 若长度相同,则按照数组value中的每一位进行比较。若不同,则返回false。若每一位都相同,则返回true。
       • 若当前传入的对象不是String类型,则直接返回false。
       • 此外StringBuffer和StringBuilder并没有重写equals方法,其比较的还是引用类型的地址。




    3.3.2 未重写equals方法的类

        如果类没有重写equals方法,其比较的还是引用类型的地址。

四、为什么重写equals方法就一定要重写hashCode方法 

先放结论:

4.1 为什么要重写equals方法

Object 类中的 equals 方法用于检测一个对象是否等于另外一个对象。在 Object 类中,这个方法将判断两个对象是否具有相同的引用。如果两个对象具有相同的引用,它们一定是相等的。​大多数情况下不重写equals方法,直接使用Object中的equals方法是没有任何意义的,不如直接使用==运算符,二者是等价的。

以下代码示例,就可以说明这个问题: 

package com.hulei.studyproject.blogtest; import lombok.Getter; / * @Title: EqualsMyClassExample * @Description: TODO * @author: hulei * @date: 2023/8/4 13:52 * @Version: 1.0 */ public class EqualsMyClassExample { public static void main(String[] args) { Person u1 = new Person(); u1.setName("Java"); u1.setAge(18); Person u2 = new Person(); u2.setName("Java"); u2.setAge(18); System.out.println(u1.equals(u2)); } } @Getter class Person{ private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } } 

输出结果如下图所示:

一文详解java中的==和equals()

可以看到两个不同的引用,不重写equals,直接调用Object类中的原始equals方法,比较结果一定是false,这种比较没有意义,因为内存地址不同,即使两个对象的内容完全相同,因此通常情况下,我们要判断两个对象是否相等,一定要重写 equals 方法,这就是为什么要重写 equals 方法的原因。

4.2 hashCode

hashCode 翻译为中文是散列码,它是由对象推导出的一个整型值,并且这个值为任意整数,包括正数或负数。​

需要注意的是:散列码是没有规律的。

     如果 x 和 y 是两个不同的对象,x.hashCode() 与 y.hashCode() 基本上不会相同;但是也有例外
    • 但如果 a 和 b 相等,则 a.hashCode() 一定等于 b.hashCode()。​

hashCode使用

package com.hulei.studyproject.blogtest; / * @Title: EqualsMyClassExample * @Description: TODO * @author: hulei * @date: 2023/8/4 13:52 * @Version: 1.0 */ public class EqualsMyClassExample { public static void main(String[] args) { String s1 = "Hello"; String s2 = "Hello"; String s3 = "Java"; System.out.println("s1 hashCode" + s1.hashCode()); System.out.println("s2 hashCode" + s2.hashCode()); System.out.println("s3 hashCode" + s3.hashCode()); // 在一些特殊情况下是相同的 String t1 = "Aa"; String t2 = "BB"; System.out.println("t1 hashCode" + t1.hashCode()); System.out.println("t2 hashCode" + t2.hashCode()); } }

结果如下:

一文详解java中的==和equals()

在java中,equals和hashcode是有设计要求的,equals相等,则hashcode一定相等,反之则不然。 为何会有这样的要求? 在集合中,比如HashSet中,要求放入的对象不能重复,怎么判定呢? 首先会调用hashode,如果hashcode相等,则继续调用equals。

4.3 为什么equas和hashCode要一起重写?

下面看几个示例:

        4.3.1 Set集合正常使用
package com.hulei.studyproject.blogtest; import java.util.HashSet; import java.util.Set; / * @Title: EqualsMyClassExample * @Description: TODO * @author: hulei * @date: 2023/8/4 13:52 * @Version: 1.0 */ public class EqualsMyClassExample { public static void main(String[] args) { Set<String> set = new HashSet(); set.add("Java"); set.add("Java"); set.add("MySQL"); set.add("MySQL"); set.add("Redis"); System.out.println("Set 集合长度:" + set.size()); System.out.println(); // 打印 Set 中的所有元素 set.forEach(System.out::println); } }

 执行结果如下:

一文详解java中的==和equals()

从上述结果可以看出,重复的数据已经被 Set 集合”合并”了,这也是 Set 集合最大的特点:去重

       4.3.2  Set集合的”异常”使用

重写equals方法

package com.hulei.studyproject.blogtest; import lombok.Getter; import java.util.HashSet; import java.util.Objects; import java.util.Set; / * @Title: EqualsMyClassExample * @Description: TODO * @author: hulei * @date: 2023/8/4 13:52 * @Version: 1.0 */ public class EqualsMyClassExample { public static void main(String[] args) { Person u1 = new Person(); u1.setName("Java"); u1.setAge(18); Person u2 = new Person(); u2.setName("Java"); u2.setAge(18); System.out.println("equals result = " + u1.equals(u2)); // 创建 Set 集合 Set<Person> set = new HashSet<>(); set.add(u1); set.add(u2); // 打印 Set 中的所有数据 set.forEach(System.out::println); } } @Getter class Person{ private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name,person.name); } /*@Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; }*/ @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } 

 执行结果如下所示:

一文详解java中的==和equals()

这就造成了equals比较结果明明是相同值,为什么Set却重复存储呢? 

再放开代码中重写的hashCode方法注释,执行结果如下所示:

一文详解java中的==和equals()

此时可以看到Set集合进行了去重。

4.4 原因分析 

默认情况下,Set 进行去重操作时,会先判断两个对象的 hashCode 是否相同,此时因为没有重写 hashCode 方法,所以会直接执行 Object 中的 hashCode 方法,而 Object 中的 hashCode 方法对比的是两个不同引用地址的对象,所以结果是 false,那么 equals 方法就不用执行了,直接返回的结果就是 false:两个对象不是相等的,于是就在 Set 集合中插入了两个相同的对象。​

但是,如果在重写 equals 方法时,也重写了 hashCode 方法,那么在执行判断时会去执行重写的 hashCode 方法,此时对比的是两个对象的所有属性的 hashCode 是否相同,于是调用 hashCode 返回的结果就是 true,再去调用 equals 方法,发现两个对象确实是相等的,于是就返回 true 了,因此 Set 集合就不会存储两个一模一样的数据了,于是整个程序的执行就正常了。

4.5 总结

      • hashCode 和 equals 两个方法是用来协同判断两个对象是否相等的,采用这种方式的原因是可以提高程序插入和查询的速度。
      • 如果只重写equals方法,不重写hashCode方法,就有可能导致a.equals(b)这个表达式成立,但是hashCode却不同。会造成一个完全相同的对象会存储在hash表的不同位置。

五、练手举例

1.下面的代码将创建几个字符串对象?3个 

分别创建了s1堆内存上的实例,s2内存上的实例,以及字符串常量池

 2.在java中,String s=new String(“xyz”)创建了几个对象?C

A 1个 B 1个或2个 C 2个 D 以上都不对

3.下面的代码输出什么?

4.下面的代码输入什么? 

5.下面的代码输出什么?

6.下面的代码输出什么?

7.下面的代码输出什么?

8.下面的代码输出什么?

9.下面的代码输入什么?

10.下面的代码输入什么?

11.下面选项结果为true的是:C

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/131721.html

(0)
上一篇 2025-08-05 21:20
下一篇 2025-08-05 21:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信