Java面试系列 No.1 —— equals 与 == 的区别
本文最后更新于:4 个月前
小声叭叭
最近想着通过面试题来巩固下自己的基础知识,在不少面试题总结中,“equals 与 == 的区别”这个问题出现频率不是一般高,虽然在自己编程中,有时候也会区分使用二者,但是既然是深究,那就来扒一扒这两者的区别。(看结论直接到最后一节【总结】)
看本质
首先,两者的作用呢都是用于比较,但是在本质上和使用上,两者还是有很大的区别的:
本质上:
==
是Java的一个运算符,而equals()
是Object类的一个用于比较的方法,这是根本上的不同。使用上:虽然在日常开发中,
==
和equals()
都会经常出现在比较两者是否相等的情况下,但是两者在适用场景上,却有着很大的不同。
先来看 “==”
首先,“==”在用于比较时,会有几种不同的情况:
- 两侧为引用类型(封装类型)
- 两侧为基本类型
一侧为引用类型一侧为基本类型
两侧为基本类型
当==
两侧为基本类型时,==
的作用为比较两者的值是否相等,比如以下的例子:
1 |
|
对于java基础类型int的两个变量a和b,值均为1222,因此输出为true。同样也适用于Java其他的全部基本类型。
Java基础类型包含:
- 数字类型:整数byte、short、int、long,浮点数:double、float
- 字符类型:char
- 布尔类型:boolean
两侧为引用(封装)类型
当==
两侧为引用(封装)类型时,比较的是引用是否相同,即除了要比较值是否相同外,还要比较值所在的内存地址是否相同.
对于绝大多数引用类型,只要使用了new
关键字来创建新的对象,则对象的引用地址也将是新的地址,此时使用==
得到的总为false。
而当第一个对象使用new,而将第一个对象直接复制给第二个对象时,第一个对象和第二个对象指向为同一个,此时使用==
等到的总为true.
除开以上两种普遍情况外,需要考虑不同类型在定义时的一些不同情况,这里重点考虑几种常用的封装类型:
- String 类型
对于String,需要引入一个字符串常量池的概念,具体的内容大家自行搜索了解 我后续也会补上相关的文章,先立flag,补上后再回来贴地址,在这里我们需要了解一些内容:
为了提高性能并减少内存的开销,JVM在实例化字符串常量时进行了一系列的优化操作:
- 在JVM层面为字符串提供字符串常量池,可以理解为是一个缓存区;
- 创建字符串常量时,JVM会检查字符串常量池中是否存在这个字符串;
- 若字符串常量池中存在该字符串,则直接返回引用实例;若不存在,先实例化该字符串,并且,将该字符串放入字符串常量池中,以便于下次使用时,直接取用,达到缓存快速使用的效果。
例如如下的代码:
1 |
|
这种情况就适用于上述的字符串常量池说法,首先在定义str1时,会先检测常量池中是否有字符串”Hello”,若没有,则创建一个新的对象”Hello”保存在内存上,然后定义str2时,检测常量池中已存在字符串”Hello”,则会将str2也指向这个字符串,此时就会出现,str1和str2的值和引用均一致,所以使用 == 比较会出现true的情况。
- 基本类型的对应封装类型
基本类型的对应封装类型表如下:
基本类型 | 对应封装类型 |
---|---|
char | Character |
boolean | Boolean |
float | Float |
byte | Byte |
double | Double |
int | Integer |
short | Short |
long | Long |
对于这些基础类型的封装类型,在Java 语言规范中,找到了关于==
的这样一句话:
大致意思就是:
- 当
==
两侧为Integer类型时,在-128~127范围内时值相等则返回true; - 当
==
两侧为Character类型时,在\u0000~\u007f范围内时值相等则返回true; - 当
==
两侧为Boolean类型时,值相等则返回true。
上述范围内的值是直接缓存在内存中的,在直接赋值的情况下,均指向这个已缓存的对象,因此会出现在上述范围内值相等时使用==
会返回true的情况。
Integer:
1 |
|
Character:
1 |
|
Boolean:
1 |
|
再看equals()
1 |
|
由此可看到,默认情况下,equals()
和==
的作用是一致的,因为在equals()
中的运算还是使用==
,对于两个引用类型使用equals()
,默认情况下还是对引用进行比较,此时只需要结合==
部分的讲解进行考虑即可。
但是,对于绝大多数的引用类型都会对equals()
进行重写,就例如在上节介绍的Integer,String等一些Java内置引用类型,亦或是我们自己定义的一些引用类型,通常情况下都会将equals()
重写为进行值的比较。例如如下的是String类型的equals()
定义:
1 |
|
其他的类似基础类型的对应引用类型的equals()
也都有各自的定义,这里不再赘述,自行查看即可。
结论
对于==
:
- 基本类型:比较的是值是否相同;
- 引用类型:比较的是引用是否相同;
对于equals()
:
本质上与==
效果一致,但大多数情况下会重写为值的比较,所以equals()
通常都用来进行值的比较。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!