深入解析==与equals()区别
本文源自 公-众-号 IT老哥 的分享
IT老哥,一个在大厂做高级Java开发的程序员,每天分享技术干货文章
前言
相信大家一定在很多地方多看到过==
与equals()
的区别,也把区别讲的很详细,每次记住了,很快又会变得模糊不清。
这时就需要从原理深入剖析,一招制敌!
认识==的用法
在Java中,==的作用有两个
(1).基础数据类型:比较的是两者的值是否相等,比如int,float,double变量。
public static void main(String[] args) {
int a = 1;
int b = 1;
float x = 3.2f;
float y = 3.2f;
System.out.println(a == b);
System.out.println(x == y);
}
此时结果,两个都为true。
(2).引用数据类型:比较的是两者的地址是否相同,比如Integer等。String是一个特殊的,后面再讨论。
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(1);
Integer c = 1;
System.out.println(a == b);
System.out.println(a == c);
}
此时结果,两个都为false。因为使用Integer类,每次都创建了新的对象,所以分配的地址是不同的。但Integer类与int作比较结果如何呢?
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(1);
int c = 1;
System.out.println(a == b);//false
System.out.println(c == a);//true
System.out.println(c == b);//true
}
输出结果:false,true,true。此时我们不难发现,当包装类与其基本类型进行比较时,会转变为对两者的值的比较。
认识equals()的用法
equals()方法源自Object类,先看一下源码是什么样:
public boolean equals(Object obj) {
return (this == obj);
}
看到这里,很快就发现equals()方法和==是相同的,所以在使用基本数据类型和引用对象(包装类除外)比较时,两者不存在区别。
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(1);
int c = 1;
System.out.println(a.equals(c));
System.out.println(b.equals(c));
}
此时结果为:true,true。当包装类与其基本类型用equals()方法进行比较时,同样比较两者的值,也不存在区别。
不同点
有一点是比较特殊的,在使用equals()方法对包装类和包装类进行比较时,则会不同。
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println(a.equals(b));//true
System.out.println(a == b); //false
}
输出结果:true,false。包装类和包装类采用equals()方法,也会转变成对值得比较。为什么呢?因为包装类重写了Object类的equals()方法。打开重写后equals()方法的源码:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
从这里可以看出,包装类和包装类的比较,就是两者值得比较。
String类中的==和equals()方法
在String中,重写了Object类的equals(),自然逻辑和功能不同了。
String类中的equals()方法
先来看看String类中equals()方法源码:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
在源码第一个判断中,若两个对象指向地址相同,则返回true。第二个判断中,若字符内容相同,则返回true。其实就是对两者值得比较。
public static void main(String[] args) {
String a = "Hello";
String b = "Hello";
System.out.println(a.equals(b));//true
}
输出结果:true。
String类中的测试
public static void main(String[] args) {
String a = "Hello";
String b = "Hello";
String c = new String("Hello");
String d = c;
System.out.println(a == b);//true
System.out.println(a == c);//false
System.out.println(c == d);//true
System.out.println(a.equals(b));//true
System.out.println(a.equals(c));//true
System.out.println(c.equals(d));//true
}
为什么出现这样的结果。可以从内存的角度来解释:
3.通过内存来解释
在Java中,一般是把对象放在堆区,对象的引用则放在了栈区。
从上图可以看出:
- 当String a = “Hello”;创建一个引用类型a,指向堆区一个位置,用于保存字符串对象;
- 当String b = “Hello”;java会到它的常量池中找"hello"是不是在常量池中已存在。如果已经存在则返回这个常量池中的"hello"的地址(在java中叫引用)给变量b;
- String c= new String(“hello world”); 会在堆区再次存放一个字符串对象;
- String d = c;当中d和c是相同的引用,指向同一个地址。
所以根据此可以判断以上输出结果:
云服务器,云硬盘,数据库(包括MySQL、Redis、MongoDB、SQL Server),CDN流量包,短信流量包,cos资源包,消息队列ckafka,点播资源包,实时音视频套餐,网站管家(WAF),大禹BGP高防(包含高防包及高防IP),云解析,SSL证书,手游安全MTP,移动应用安全、 云直播等等。
//true 指向同一个地址
System.out.println(a == b);
//false 指向不同地址
System.out.println(a == c);
//true 指向同一个地址
System.out.println(c == d);
//true 地址指向的内容相同
System.out.println(a.equals(b));
//true 地址指向的内容相同
System.out.println(a.equals©);
//true 地址指向的内容相同
System.out.println(c.equals(d));
- CentOS 6 使用 yum 安装MongoDB及服务器端配置
- java处理高并发高负载类网站的优化方法
- 每一个程序员需要了解的10个Linux命令
- php_curl.dll libssh2.dll 始终无法加载的原因 及解决办法
- ant安装、环境变量配置及验证
- MySQL性能优化的最佳20+条经验
- 剑指offer面试题7——用两个栈实现队列
- String类中你不知道的知识
- Hibernate 不同数据库的连接及SQL方言
- Java中被你忽视的四种引用
- 使用Python和R语言从头开始理解和编写神经网络
- 深度学习中训练参数的调节技巧
- 大型网站技术架构!
- 理解js中的原型链,prototype与__proto__的关系
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python内置方法和属性应用:反射和单例(推荐)
- 使用OpenCV对车道进行实时检测的实现示例代码
- php 读取文件夹下所有图片、文件的实例
- php微信公众号开发之欢迎老朋友
- Linux基于php-fpm模式的lamp搭建phpmyadmin的方法
- PHP使用glob方法遍历文件夹下所有文件的实例
- Python图像阈值化处理及算法比对实例解析
- 浅析Python 条件控制语句
- 浅谈Django前端后端值传递问题
- sklearn和keras的数据切分与交叉验证的实例详解
- django Model层常用验证器及自定义验证器详解
- PyQT5 实现快捷键复制表格数据的方法示例
- Python爬虫headers处理及网络超时问题解决方案
- python报错: 'list' object has no attribute 'shape'的解决
- Python应用实现双指数函数及拟合代码实例