Java基础系列-深入理解==和equals的区别(一)
一、前言
说到==和equals的问题,面试的时候可能经常被问题到,有时候如果你真的没有搞清楚里边的原因,被面试官一顿绕就懵了,所以今天我们也来彻底了解一下这个知识点。
二、==和equals的作用
2.1 ==的作用
在java中我们用==来判断两个变量是否相等,但是会根据数据类型有所区别:
1.对于8种基础数据类型(byte、short、int、long、double、float、boolean、char)来说==是判断变量的数值是否相等。
byte y1 = 1, y2 = 1;
short s1 = 1, s2 = 1;
int i1 = 1, i2 = 1;
long l1 = 1, l2 = 1;
double d1 = 1, d2 = 1;
float f1 = 1, f2 = 1;
boolean b1 = true, b2 = true;
char c1 = 1, c2 = 1;
System.out.println("byte:y1==y2 " + (y1 == y2));
System.out.println("short:s1==s2 " + (s1 == s2));
System.out.println("int:i1==i2 " + (i1 == i2));
System.out.println("long:l1==l2 " + (l1 == l2));
System.out.println("double:d1==d2 " + (d1 == d2));
System.out.println("float:f1==f2 " + (f1 == f2));
System.out.println("boolean:b1==b2 " + (b1 == b2));
System.out.println("char:c1==c2 " + (c1 == c2));

对于引用类型,==比较的是引用的地址是否相等:
Object o1 = new Object();
Object o2 = o1;
Object o3 = new Object();
System.out.println("Object:o1 == o2 " + (o1 == o2));
System.out.println("Object:o1.equals(o2) " + (o1.equals(o2)));
System.out.println("Object:o1 == o3 " + (o1 == o3));
System.out.println("Object:o1.equals(o3) " + (o1.equals(o3)));

接下来我们来看看equals里的内部实现,其实还是调用的==:

总结:所以说对于==,当数据类型是8大基础类型时,比较的是(栈中)数值是否相等,当数据类型是引用类型时,比较的是对象的引用地址是否相等。这是通过jvm来自动判断的。
2.2 equals的作用
equals是object类中的一个方法,也就是说使用equals必须是对象类型,所以equals比较的是对象是否相当,默认情况上边已经说过了使用的就是==,但是别忘了equals是基类中的方法,是可以重写的,当我们重写的时候就可以实现不同的功能了。
那么对于字符串,也是一种引用类型,我们先来看看下面这个例子:
String str1 = "123",str2 = "123";
String str3 = new String("123");
String str4 = new String("123");
System.out.println("String:str1 == str2 " + (str1 == str2));
System.out.println("Object:str1.equals(str2) " + (str1.equals(str2)));
System.out.println("Object:str1 == str3 " + (str1 == str3));
System.out.println("Object:str1.equals(str3) " + (str1.equals(str3)));
System.out.println("Object:str3 == str4 " + (str3 == str4));
System.out.println("Object:str3.equals(str4) " + (str3.equals(str4)));

这里我们介绍一个概念,叫做字符串拘留池:由于字符串这种东西在我们的程序中非常的常用,每一个字符串都要创建对象,花费开销,但是通常字符串一般的我们只关心它的值是什么,所以jvm在这里做了一个优化,当字符串在拘留池(一块存储字符串的地方)里出现的时候,如果下次我们又用到了这个字符串,就直接返回池子里字符串的地址,因为值都是一样的,减少了开销,如果没有,就放进池子里,以备后来有用到的时候,相当于一个缓存了。
所以当我们执行String str1 = "123",str2 = "123"; 实际上两个变量指向的是同一个地址,所以自然的str1 == str2和str1.equals(str2)是一样的,都为true,没毛病。
当我们使用String str3 = new String("123");很明显示开辟了一块新的内存地址,只不过存储的值是123是一样的,所以str1 == str3是false,没毛病,但是按理说str1.equals(str3)也应该是false啊,之前不是说内部也是用的==吗,我们可以看一下字符串类中equals的实现:

很明显,在实现判断了地址是否相同以后,这里边又做了判断,字符串的值是否相等,如果相等就返回true,到这里为止,我们已经真相大白了,原来String类重写equals方法,判断的是字符串的值是否相等,而不仅仅是地址。所以自然的我们的str1.equals(str3) 是true了。
那么由此可知,str3 == str4 比较的是地址,明显不一样,因为是new了两个对象,所以返回false,str3.equals(str4)比较的是字符串的值,所以返回true,也没毛病。
总结:因为我们在对字符串比较的时候,往往关注的就是值一样不一样,所以java这样重写也是 很有必要的,所以我们一直推荐判断字符串相等用equals方法,而不是用==来判断。equals方法具体产生什么样的效果,完全看子类是怎么重写的,比如Date类,重写了equals方法,只要两个时间的getTime()时间戳一样,那么就相等,这也是符合我们的认知的。

所以,在我们以后需要判断两个对象相等的用equals的时候,我们可以完全根据自己的业务来重写equals方法,比如两个Person实例,如果id一样,我们就应该认为他们俩是相等,这个时候我们就可以重写equals方法,用id作比较来返回值。
三、总结
这次终于搞明白了==和equals的用法和作用,以后学什么东西还必须要深入理解一下内部原理才行,这样就不怕面试官再来搞事情了。
Java基础系列-深入理解==和equals的区别(一)的更多相关文章
- Java基础系列-equals方法和hashCode方法
原创文章,转载请标注出处:<Java基础系列-equals方法和hashCode方法> 概述 equals方法和hashCode方法都是有Object类定义的. publi ...
- 夯实Java基础系列9:深入理解Class类和Object类
目录 Java中Class类及用法 Class类原理 如何获得一个Class类对象 使用Class类的对象来生成目标类的实例 Object类 类构造器public Object(); register ...
- 夯实Java基础系列13:深入理解Java中的泛型
目录 泛型概述 一个栗子 特性 泛型的使用方式 泛型类 泛型接口 泛型通配符 泛型方法 泛型方法的基本用法 类中的泛型方法 泛型方法与可变参数 静态方法与泛型 泛型方法总结 泛型上下边界 泛型常见面试 ...
- Java基础系列1:深入理解Java数据类型
Java基础系列1:深入理解Java数据类型 当初学习计算机的时候,教科书中对程序的定义是:程序=数据结构+算法,Java基础系列第一篇就聊聊Java中的数据类型. 本篇聊Java数据类型主要包括四个 ...
- Java基础系列2:深入理解String类
Java基础系列2:深入理解String类 String是Java中最为常用的数据类型之一,也是面试中比较常被问到的基础知识点,本篇就聊聊Java中的String.主要包括如下的五个内容: Strin ...
- 夯实Java基础系列10:深入理解Java中的异常体系
目录 为什么要使用异常 异常基本定义 异常体系 初识异常 异常和错误 异常的处理方式 "不负责任"的throws 纠结的finally throw : JRE也使用的关键字 异常调 ...
- 夯实Java基础系列11:深入理解Java中的回调机制
目录 模块间的调用 多线程中的"回调" Java回调机制实战 实例一 : 同步调用 实例二:由浅入深 实例三:Tom做题 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 ...
- 夯实Java基础系列14:深入理解Java枚举类
目录 初探枚举类 枚举类-语法 枚举类的具体使用 使用枚举类的注意事项 枚举类的实现原理 枚举类实战 实战一无参 实战二有一参 实战三有两参 枚举类总结 枚举 API 总结 参考文章 微信公众号 Ja ...
- Java基础系列--HashMap(JDK1.8)
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10022092.html Java基础系列-HashMap 1.8 概述 HashMap是 ...
随机推荐
- k好数(动态规划)
问题描述 如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数.求L位K进制数中K好数的数目.例如K = 4,L = 2的时候,所有K好数为11.13.20.22 ...
- 单元测试之NUnit三
NUnit 分三篇文章介绍,入门者可阅读文章,有基础者直接参考官方文档.初次写博客,望大家指点. 导航: 单元测试之NUnit一 单元测试之NUnit二 单元测试之NUnit三 除了Assert断言外 ...
- odoo项目结构参数属性详解
1.基础文件及目录结构 在认识odoo ORM框架前,先介绍一下odoo中模块目录结构. data:存放模块预制数据i18n:存放国际化文件models:存放模型等py代码security:存放权 ...
- 本地图片上传到GitHub,MarkDown使用Github图片地址
最近在学习用markdown编辑器,我是直接用有道云笔记编辑的,感觉真的好好用,编辑了一半的博客,可以按样式保存在云笔记中,我再也不会忘记写博客了~~ 但是在编辑博客的时候发现了一个问题,那就是本地图 ...
- 装饰器修复技术@wraps
@wrap修复技术 首先我先说一下wrap的效果 如果没使用@wraps,当A调用了装饰器B的话,即使A.name,返回的会是装饰器B的函数名称,而不是A的函数名称如果使用了@wraps,当A调用了装 ...
- Java性能测试从入门到放弃-详解篇
Jmeter组件分类说明 Jmeter的组件可以放在任意位置 线程池:用于创建线程.每个线程会"批次顺序"执行任务,因此后面的任务可根据前面的任务决定具体的操作. ...
- 计算机基础+python初阶
今日内容: 1.计算机基础知识 2.python简介 3.快速入门 今日内容: 一.计算机基础 1. 计算机什么组成的 输入输出设备 cpu 硬盘 内存 中央处理器 处理各种数据 相当于人的大脑 内存 ...
- Attention机制的精要总结,附:中英文机器翻译的实现!
1. 什么是Attention机制 在"编码器-解码器(seq2seq)"⼀节⾥,解码器在各个时间步依赖相同的背景变量来获取输⼊序列信息.当编码器为循环神经⽹络时,背景变量来⾃它最 ...
- 正则表达式-Regex详解
1.什么是正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑.给定一个正 ...
- npm init,npm -y, npm install --save,npm install --save-dev
npm init 初始化一个简单的package.json文件,执行该命令后终端会依次询问 name, version, description 等字段 npm init --yes|-y 作用同上, ...