前言

  在我们Java面试中,基础知识基本上比定会考核的点,而“==和equals的区别”则是面试官最喜欢、最经常问的问题。

  但我们看了不少的文章、解释,总是一头雾水、一知半解的,往往很容忘记。今天,我带大家从底层去深入理解这两个玩意的区别,相信下次面试官再问的时候,肯定能镇住面试官

一、初始“==”的含义

  在Java中,“==”的作用主要有两个:

  1、基础数据类型:比较的是两者的值是否相等,比如两个 int 类型的变量,比较的是变量的值是否相等。

  2、引用数据类型:比较的是引用地址是否相同,比如新建了两个 User 对象,比较的是两个 User 的地址是否一样。

  到这里,有些人就有会疑问了:你这里怎么用了个User对象,怎么不是String?别急,请允许我卖个关子。

二、理解equals的含义

  我们通过Object的源码,先看看Object里面的equals方法

  通过源码,我们可以看到equals方法比较的是当前对象的引用和 obj 的引用是否相同,也就是说默认比较的就是地址

  我们刚才使用的是 User 对象而不是String,在这里“==”比较的就是引用地址,“equals”也是比较引用地址,这两者是没有区别的。

public class MobileTestBase {

    public static void main(String[] args) {

        int a = 2;
int b = 2;
//常量比较的是两者的值,故为 ture;
System.out.println(a==b); User user1 = new User();
User user2 = new User();
//普通对象User,"=="和"equals"作用是一样,比较两者的引用地址,均为 false
System.out.println(user1==user2);
System.out.println(user1.equals(user2));
}
}

  到这里,我们发现,好像“==”和“equals”并没有什么区别,但是,接下来的String类型,就有点意思了,且听我徐徐道来。

三、重写equals

  1、String中的equals方法

  看到标题,相信我们已经有点印象了,Object对象里面的“==” 和 “equals” 没有什么区别,这样的 equals 方法是没有什么意义的。

  但是,我们可以看到 String 在 Object 的基础上对 equals 进行重写,那么 equals 的逻辑、功能自然就发生变化了。至于怎么重写,我们一起到 String 源码中寻找答案吧。

  从源码中可以看出:String 中的 equals 方法是在比较字符串的内容是否一样。也就是说,如果像 String、Date 这些重写 equals 的类,在使用的时候会和 Object 的 equals 不一样。

  2、测试String

  看看下面的测试代码:

public class Test {

    public static void main(String[] args) {

        String str1 = "hello world";
String str2 = new String("hello world");
String str3 = str2; //赋值,引用传递; System.out.println(str1 == str2); // false
System.out.println(str1 == str3); // false
System.out.println(str2 == str3); // true System.out.println(str1.equals(str2)); // true
System.out.println(str1.equals(str3)); // true
System.out.println(str2.equals(str3)); // true
}
}

  可以看到,定义了3个字符串,分别使用“==” 和 “equals” 比较,出现了不同的结果。其中的原因,就需要我们从内存的角度去解释了。

  3、内存解释

  在Java中,我们一般把对象存放在堆区,把对象的引用存放在栈区。因此,上面3个字符串的内存状态应该是下面这样的。

  从上图我们可以看出来:

  1. String str1 = "hello world"; 会在堆区存放一个字符串对象;
  2. String str2 = new String("hello world"); 会在堆区再次存放一个字符串对象;
  3. String str3 = str2; 这时候 str3 和 str2 是两个不同的引用,但是指向同一个对象。

  借助于上图,我们再次比较:

  1. str1 == str2 ? 即地址指向的是同一个地方吗? 当然是 false
  2. str1 == str3 ? 即地址指向的是同一个地方吗? 当然是 false
  3. str2 == str3 ? 即地址指向的是同一个地方吗? 明显内容是一样的,当然是 true
  4. str1.equals(str2) ? 即地址指向的内容相同吗? true
  5. str1.equals(str3) ? 即地址指向的内容相同吗? true
  6. str2.equals(str3) ? 即地址指向的内容相同吗? true

  到了这里,不知道我们是否能理解?

四、总结

  1、基础数据比较

    使用“==”是比较值是否相等

  2、引用数据比较

  • 重写了equals方法,比如String类。

    • “==”    :比较的是String的引用是否指向同一块内存
    • “equals”:比较的是String的引用的对象内容是否相等;  
  • 没有重写equals方法,如User等自定义类。
    • “==” 和 “equals” 比较的都是引用是否指向了同一块内存

五、其他

  String 类型还没结束,有一个小知识点需要注意下,如下:

public class Test {

    public static void main(String[] args) {
String str1 = "hello world";
String str2 = new String("hello world"); str2 = str2.intern(); System.out.println(str1 == str2); //true
System.out.println(str1.equals(str2)); //true
}
}

  细心就会发现,中间多了个 intern 方法。这个方法表示,检查字符串池中是否存在,如果存在,那就直接返回 true。因为这里 str1 首先会在字符串池里面有一个,然后 str2.intern() 发现池子里有了,就不再新建了,直接把 str2 指向它。

《面试经典系列》- 从底层理解==和equals的区别的更多相关文章

  1. Java基础系列-深入理解==和equals的区别(一)

    一.前言 说到==和equals的问题,面试的时候可能经常被问题到,有时候如果你真的没有搞清楚里边的原因,被面试官一顿绕就懵了,所以今天我们也来彻底了解一下这个知识点. 二.==和equals的作用 ...

  2. 《面试经典系列》- SpringMVC原理及工作流程

    前言 SpringMVC 作为 MVC 的开源框架,现在依旧是不少项目使用的重点框架.SpringMVC = Struts2 + Spring,SpringMVC就相当于 Struts2 + Spri ...

  3. 《面试经典系列》- MySQL数据库存储引擎

    一.MySQL有多少种存储引擎? 在MySQL5之后,支持的存储引擎有十多个,但是我们常用的就那么几种,而且,默认支持的也是 InnoDB. 通过命令:show engines \g,我们可以查看到当 ...

  4. 关于==和equals的区别和联系,面试这么回答就可以

    长篇大论的话,我这里就不多写了,相信大家入门java 的时候就知道个大概了,这里想表述的是,如果面试官问你<关于==和equals的区别>,该怎么回答完美呢?可以这样说 总结的来说: 1) ...

  5. 别傻傻不知道 == 和 equals 的区别【面试系列】

    ​ 关于这个问题,一般初中级面试中都会遇到,还记得我当初实习找工作的时候也遇到了这个问题,现在都还记得自己是怎么回答的:== 是基本类型比较,equals 是对象比较,不懂 hashCode,想起来简 ...

  6. 面试经典算法题集锦——《剑指 offer》小结

    从今年 3 月份开始准备找实习,到现在校招结束,申请的工作均为机器学习/数据挖掘算法相关职位,也拿到了几个 sp offer.经历这半年的洗礼,自己的综合能力和素质都得到了一个质的提升. 实话说对于未 ...

  7. Java基础系列之你真的懂==与equals的区别吗?

    对于Java初学者而言,可能会对这两个比较方法比较模糊,有的人可能会觉得两个的方法使用起来结果是一样的等.如果你有这样的想法,我建议你来看看这边博客,让你充分了解这两个比较的异同,以及他们底层是如何比 ...

  8. Java面试炼金系列 (1) | 关于String类的常见面试题剖析

    Java面试炼金系列 (1) | 关于String类的常见面试题剖析 文章以及源代码已被收录到:https://github.com/mio4/Java-Gold 0x0 基础知识 1. '==' 运 ...

  9. 让代码重构渐行渐远系列(3)——string.Equals取代直接比较与非比较

    重构背景及原因 最近由于项目组的人员在不断扩充,导致项目中代码风格各异,大有百花齐放甚至怒放之势.考虑到团队的生存与发展,经过众人多次舌战之后,最终决定项目组根据业务分成几个小分队,以加强团队管理与提 ...

随机推荐

  1. Docker学习笔记_04 Rancher的部署安装(编排选用K8S)

    原文地址:http://dbase.cc/2018/01/12/docker/04_rancher的部署安装/ 为什么要使用Rancher Rancher是一个开源的企业级容器管理平台.通过Ranch ...

  2. JavaScript if为true的情况

    变量如果不为0,null,undefined,false,都会被处理为true.只要变量有非0的值或是某个对象,数组,字符串,都会认为true

  3. 2016/11/10 吃吃喝喝Hacking Thursday Night聚餐活动 at Dunkin Donuts

    店名:Dunkin Donuts 唐恩都乐 点评:http://www.dianping.com/shop/21378231 地址:静安区南京西路1649号静安公园内(近静安公园) 走法:地铁2号线静 ...

  4. 少用 string.Format

    如果你使用的是 C# 6.0 及其以上版本的话我建议你使用新增的 内插字符串 这个功能.这个功能可以更好的帮助开发人员设置字符串格式.下面我们就来看一下为什么要少用 string.Format 而要多 ...

  5. flask 返回json数据

    ret={ 'a':1 } return jsonify(ret) 不能直接返回ret,应该用jsonify().这样返回的Content-Type: application/json;charset ...

  6. 量化投资学习笔记31——《Python机器学习应用》课程笔记05

    用分类算法进行上证指数涨跌预测. 根据今天以前的150个交易日的数据,预测今日股市涨跌. 交叉验证的思想:将数据集D划分为k个大小相似的互斥子集,每个子集都尽可能保持数据分布的一致性,即从D中通过分层 ...

  7. 自定义 ---UICollectionViewLayout-正N变形居中布局

    1. 自定义UICollectionLayout ---- 正三角形居中布局 支持多个图形的自动布局 2. 自定义UICollectionLayout ---- 正方形居中布局 滚动展示的区域 3.  ...

  8. Murata村田研发向左,制造向右

    前言:Murata村田自1944 年在日本京都创立,是陶瓷无源电子元件.无线连接模块和电源转换技术产品设计和制造领域的全球领导者. Murata 一直在为社会的进步和电子行业的革命贡献自己的力量. 在 ...

  9. 差分放大电路的CMRR与输入电阻分析

    分析了经典差分放大电路的共模抑制比CMRR与输入电阻RIN 1.经典差分放大电路 基于运放的经典差分放大电路在各模电教材中均能找到,利用分离电阻和运算放大器实现,如图1所示为一种差分放大电路: 图1 ...

  10. Linux进程操作记录

    关于Gunicorn如何终止进程: 1.用进程树显示主进程PID: pstree -ap | grep gunicorn 2.如果有daemon进程无法用kill -9删除(可能是因为daemon屏蔽 ...