详解Java中==和equals()的区别

 更新时间:2021年11月09日 09:42:33   作者:Code花卷  
这篇文章主要介绍了Java中==和equals()的区别,,==可以使用在基本数据类型变量和引用数据类型变量中,equals()是方法,只能用于引用数据类型,需要的朋友可以参考下

1. ==

== 是运算符,用来判断两个值是否相等,==可以使用在基本数据类型变量引用数据类型变量

1.1 基本数据类型

Java基本数据类型共有八种,可以分为三类

  • 字符类型char
  • 布尔类型boolean
  • 数值类型byte、short、int、long、float、double

这里有个例外,boolean不参与数值运算

int a1 = 10;
int a2 = 10;
System.out.println(a1==a2);  //true

float a3 = 5.0f;
float a4 = 5.0f;
System.out.println(a3==a4);  //true

……

上面给出几组示例,相同数据类型可以相互比较不用多说了,那么不同数据类型呢?

int a1 = 10;
byte b1 = 10;
System.out.println(a1==b1);  //true

char c1 = 'A';
int c2 = 65;
System.out.println(c1 == c2);  //true

int a1 = 10;
double d1 = 10.0d;
System.out.println(a1==d1);  //true

int a1 = 10;
char e1 = 10;
System.out.println(a1==e1);  //true

可以看到,在基本数据类型的范围内,不同数据类型也是可以直接比较的

如果比较的是基本数据类型,就是判断两个保存的数据是否相同(不一定类型相同)

1.2 引用数据类型

这里先写一个Student类,用于参考

public class Student {
    public String name;
    public int age;

    public Student(){}

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

实例化两个Student对象,判断是否相等

Student student1 = new Student("Tom", 18);
Student student2 = new Student("Tom", 18);
System.out.println(student1==student2);  //false

注意,这里出现了示例中的第一个false。可以看到,即使赋的值是相同的,但使用==判断的结果为false,这是因为两个对象在内存中不指向同一地址。

如果比较的是引用类型,就是比较两个变量是否代表同一对象实体,也就是是否指向同一地址

1.3 小结

==是运算符
可以使用在基本数据类型变量和引用数据类型变量中
如果比较的是基本数据类型,就是判断两个保存的数据是否相同,不一定类型相同
如果比较的是引用类型,就是比较两个变量是否代表同一对象实体,也就是是否指向同一地址

2. equals

equals()是方法,只能用于引用数据类型

还是使用上面介绍到的Student对象,如果使用equals比较,那么?

Student student1 = new Student("Tom", 18);
Student student2 = new Student("Tom", 18);
System.out.println(student1.equals(student2));  //false

答案还是false,我们可以看一下在此处使用的equals的源码

image-20211107192723195

使用的正是Object中的equals()方法(继承),而Object中的equals()方法也是使用的==进行的比较

Object类中equals()和==的作用相同

诶,部分同学可能想说了,这个equals()和我们平时用的不太一样啊,平时用的equals()好像是用来比较数值的。这里我们拿String类来举例。

String str1 = new String("cun");
String str2 = new String("cun");
System.out.println(str1==str2);  //false
System.out.println(str1.equals(str2));  //true

使用==比较,不出意外是false。而这里使用equals(),得到的结果是true。我们看一下这里的equals()源码(Java8版本)

image-20211107194053016

可以看到,String类中的equals()重写了Object类中的equals(),这里侧重于具体的数值比较(我们日常使用中也是更希望比较具体的数值)。分析一下源码,这里先使用==进行比较,然后判断是否为String的一个示例,判断长度是否相等,最后挨个判断字符是否相等。

源码的大部分程序都比较好理解,有些人比较迷惑这里的强制转换(如下图),既然前一句判断了是否为String类的实例,后一句为什么还要强转?这是因为,在Java中,代码从编写到执行要经历两个过程——编译和执行,在执行时,程序判断了实参是否为String类的实例对象,之后不再需要强转;但是在编译中,即使经历了instanceof判断,编译器还是会始终把传进来的参数当作Object类型,而Object类型是没有value属性的,会直接报错。所以在这里如果不强转,编译都通不过,更不用说执行了。

image-20211107203752851

类似的,我们可以写出Student类中重写的equals()方法。

不过现在因为类使用的非常多,一方面是因为每个类都添加比较繁琐,另一方面我们可能写的可能不够健壮,这里提供两种方式自动提供equals()的重写

IDEA编译器的快捷键“alt + insert”,选择如下图的选项

image-20211107195903003

选择需要添加到equals()的属性

image-20211107200057910

可以看到自动生成的程序

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Student student = (Student) o;
    return age == student.age &&
        Objects.equals(name, student.name);
}

导入lombok包,加入Data注解

@Data
public class Student {
    public String name;
    public int age;

    public Student(){}

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

可以看到重写了Object类中的equals()方法

image-20211107200459624

3. 总结

	/**
     * ==是运算符,equals是方法
     * 1. ==
     *      可以使用在基本数据类型变量和引用数据类型变量中
     *      如果比较的是基本数据类型,就是判断两个保存的数据是否相同,不一定类型相同
     *      如果比较的是引用类型,就是比较两个变量是否代表同一对象实体,也就是是否指向同一地址
     *
     * 2. equals
     *      只能适用于引用数据类型
     *      Object类中equals()和==的作用相同
     *      像String、Data、File、包装类等中的equals都是重写了Object类中的equals()方法,比较的是实体内容是否相同
     */

到此这篇关于Java中==和equals()的区别的文章就介绍到这了,更多相关Java ==和equals()区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 实例分析java对象的序列化和反序列化

    实例分析java对象的序列化和反序列化

    序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等。在网络传输过程中,可以是字节或是XML等格式。而字节的或XML编码格式可以还原完全相等的对象。这个相反的过程又称为反序列化
    2018-09-09
  • Java设计模式之工厂模式

    Java设计模式之工厂模式

    这篇文章主要为大家详细介绍了Java设计模式之工厂模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • spring级联属性赋值的两种方式解析

    spring级联属性赋值的两种方式解析

    这篇文章主要介绍了spring级联属性赋值的两种方式解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • JAVA程序内存溢出问题原因分析

    JAVA程序内存溢出问题原因分析

    这篇文章主要介绍了JAVA程序内存溢出问题原因,较为详细的分析java导致程序内存溢出的原因与解决方法,需要的朋友可以参考下
    2015-06-06
  • 教你如何使用Java多线程编程LockSupport工具类

    教你如何使用Java多线程编程LockSupport工具类

    在Java工具包中有一个LockSupport工具类,主要负责挂起和唤醒线程,这篇文章主要介绍了教你如何使用Java多线程编程LockSupport工具类,需要的朋友可以参考下
    2021-04-04
  • Java线程在什么情况下可以终止

    Java线程在什么情况下可以终止

    Thread线程类自带的stop方法,但是jdk不建议使用,因为stop方法终止线程只是强行终止,内存中部分值可能已发生变化,并未保证数据的一致性,将会导致线程安全问题,那么在什么情况下可以终止线程呢,本篇带你探究一下
    2022-04-04
  • spring boot 利用注解实现权限验证的实现代码

    spring boot 利用注解实现权限验证的实现代码

    这篇文章主要介绍了spring boot 利用注解实现权限验证的实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • Hadoop MultipleOutputs输出到多个文件中的实现方法

    Hadoop MultipleOutputs输出到多个文件中的实现方法

    这篇文章主要介绍了 Hadoop MultipleOutputs输出到多个文件中的实现方法的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
    2017-10-10
  • 深入了解Java中Synchronized关键字的实现原理

    深入了解Java中Synchronized关键字的实现原理

    synchronized是JVM的内置锁,基于Monitor机制实现,每一个对象都有一个与之关联的监视器 (Monitor),这个监视器充当了一种互斥锁的角色,本文就详细聊一聊Synchronized关键字的实现原理,需要的朋友可以参考下
    2023-06-06
  • 再也不用怕! 让你彻底搞明白Java内存分布

    再也不用怕! 让你彻底搞明白Java内存分布

    做Java的大都没有c++ 的那种分配内存的烦恼,因为Java 帮我们管理内存,但是这并不代表我们不需要了解Java的内存结构,因为线上经常出现内存的问题,今天聊一下内存的问题,需要的朋友可以参考下
    2021-06-06

最新评论