部分面试资料链接:https://pan.baidu.com/s/1qDb2YoCopCHoQXH15jiLhA

密码:jsam

想获得全部面试必看资料,关注公众号,大家可以在公众号后台回复“知乎”即可。

“判断两个事物是否相等”,是编程中最常见的操作之一,在Java中,判断是否相等有两种方法,一种是使用“==”判断符,另一种是使用“equals()”方法,你是否曾因混用二者导致不可思议的bug?本篇文章将带你深入二者背后的判断原理。

相等判断符"=="

"=="相等判断符用于比较基本数据类型和引用类型数据。当比较基本数据类型的时候比较的是数值,当比较引用类型数据时比较的是引用(指针)。

"=="判断基本类型数据

基本数据类型指的是Java中的八大数据类型:byte,short,int,long,float,double,char,boolean。

这八大基本数据类型有个共同的特点是它们在内存中是有具体值的, 比如说一个 int 类型的数据"2",它在8位数据总线的机器上保存形式为 0000 0010。(8位机器是假设的)

当使用 == 比较两个基本数据类型的时候, 就是在比较它们各自在内存中的值。

为了照顾到要刨根问底的同学,再补充一下两个数值是怎么比较的:cpu 在比较的时候会将两个值作差,然后查看标志寄存器。标志寄存器存放的是运算的结果,里面有一个是否为0的标志位,如果该位为1,证明二者之差为0,二者相等。

"=="判断引用类型数据

引用数据类型在字面上也是很好理解的, 它就是一个引用, 指向堆内存中一个具体的对象。

比如说Student stu = new Student(); 这里的 stu 就是一个引用,它指向的是当前 new 出来的 Student 对象. 当我们想要操作这个 Student 对象时, 只需要操作引用即可, 比如说int age = stu.getAge();

所以用"=="判断两个引用数据类型是否相等的时候,实际上是在判断两个引用是否指向同一个对象

看下面的示例:

public static void main(String[] args) {String s1 = "hello";    //s1指向字符串常量池中的"hello"字符串对象String s2 = "hello";    //s2也指向字符串常量池中的"hello"字符串对象System.out.println(s1 == s2);   //trueString s3 = new String("hello");   //s3指向的是堆内存中的字符串对象 System.out.println(s1 == s3);    //false
}

从上面的例子可以看到,由于引用"s1"和"s2"指向的都是常量池中的"hello"字符串,所以返回true。(后面我会发布一篇详细讲述Java字符串的文章,涉及字符串初始化和字符串常量池等知识)

而"s3"指向的是新创建字符串对象,因为只要动用了new关键字, 就会在堆内存创建一个新的对象。

也就是说 s1 和 s3 指向的是不同的字符串对象,所以返回false。

相等判断方法equals()

equals()和 == 有着本质的区别,== 可以看作是对“操作系统比较数据手段”的封装,而equals()则是每个对象自带的比较方法,它是Java自定义的比较规则。

equals()和 == 的本质区别更通俗的说法是:==的比较规则是定死的,就是比较两个数据的值。

而 equals() 的比较规则是不固定的,可以由用户自己定义。

看下面的例子:

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

回想前面的案例:用 == 比较的时候, 上面 s1 和 s3 比较出的结果为false。而当用 equals() 比较的时候,得出的结果为 true。

想知道原因我们还得看源码,下面是 String 类中的 equals() 方法的源码。

public boolean equals(Object anObject) {if (this == anObject) {    //先比较两个字符串的引用是否相等(是否指向同一个对象), 是直接返回truereturn 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;
}

从上面的源码可以看到, 当调用 String 类型数据的 equals() 方法时,首先会判断两个字符串的引用是否相等,也就是说两个字符串引用是否指向同一个对象,是则返回true。

如果不是指向同一个对象,则把两个字符串中的字符挨个进行比较。由于 s1 和 s3 字符串都是 "hello",是可以匹配成功的,所以最终返回 true。

思考:为什么要设计equals()方法?

通过上面的讲解,相信你已经知道 == 和 equals() 的区别了:一个的比较规则是定死的,一个是可以由编程人员自己定义的。

可是为什么会有 equals() 方法, 而且还可以被自由定制呢?

这个问题要落到Java语言的核心 —— 面向对象思想了。

Java 不同于面向过程的C语言,Java是一款面向对象的高级语言。如果是面向过程编程,直接操作内存上存储的数据的话,用 == 所定义的规则来判断两个数据是否相等已经足够了。

而Java中万物皆对象,我们经常要面临的问题是这两个对象是否相等,而不是这两串二进制数是否相等,仅有 == 是完全不够用的。

由于Java程序员们会创建各种满足它们业务需求的对象,系统无法提前知道两个对象在什么条件下算相等,Java干脆把判断对象是否相等的权力交给编程人员

具体的措施是:所有的类都必须继承 Object 类,而 Object 类中写有equals()方法。编程人员可以通过重写 equals() 方法来实现自己的比较策略,也可以不重写,使用Object类的equals()比较策略。

//Object类中的equals()方法源码
public boolean equals(Object obj) {return (this == obj);
}

从 Object 类的 equals() 源码可以看到,如果编程人员没有显示地重写 equals() 方法,则默认比较两个引用是否指向同一个对象。

补充: 关于基本数据类型包装类的比较

由于 Java 中万物皆对象,就连基本数据类型也有其对应的包装类,那么它们对应的比较策略是什么呢?

public static void main(String[] args) {int a = 3;Integer b = new Integer(3);System.out.println(b.equals(a));    //true, 自动装箱
}

从上面的代码可以看到尽管两个引用不同, 但是输出的结果仍为 true, 证明 Integer 包装类重写了 equals() 方法,追踪其源码:

//Integer类中的equals方法
public boolean equals(Object obj) {if (obj instanceof Integer) {return value == ((Integer)obj).intValue();}return false;
}

从源码看到,基本类型包装类在重写equals()后,比较的还是基本数据类型的值。

结束

通过探索 == 和 equals() 的区别,我们摸清楚了二者别后的比较策略,同时也对 Java 中 equals() 方法的设计进行了思考,相信大家在今后的 Java 编程实战中不会再为相等判断而烦恼了。

部分面试资料链接:https://pan.baidu.com/s/1qDb2YoCopCHoQXH15jiLhA

密码:jsam

想获得全部面试必看资料,关注公众号,大家可以在公众号后台回复“知乎”即可。

java byte 判断相等_你真的了解Java中quot;==quot;和equals()的区别?相关推荐

  1. java byte 判断相等_转发收藏 | 史上最全Java面试题+面试网站推荐!(含答案)

    今天要谈的主题是关于求职,求职是在每个技术人员的生涯中都要经历多次.对于我们大部分人而言,在进入自己心仪的公司之前少不了准备工作,有一份全面细致面试题将帮助我们减少许多麻烦. 相关概念 面向对象的三个 ...

  2. java byte 判断相等_深入理解Java装箱与拆箱

    写给小白看的Java基础知识,阅读本文大概需要7分钟 Java中有8种基础数据类型,boolean,char,byte,short,int,long,float,double.从jdk5开始提供了自动 ...

  3. java 判断类型_如何快速入门Java编程学习(干货)

    一.初识Java 1.生活中的程序: 从起床到教室上课的过程 穿衣打扮>起床>洗漱>出宿舍>>吃早餐>到教室 按照特定的顺序去完成某一件事的过程我们叫做生活中的程序 ...

  4. java中引用类型_您真的了解Java中的4种引用类型吗?

    Java中提供了四个级别的引用:SoftReference,FinalReference,WeakReference和PhantomReference.在四种引用类型中,只有FinalReferenc ...

  5. java 精通_你真的精通Java吗?

    简历和自我介绍上经常能够读到"精通Java"这样的话,有人和我说,精通Java的人太多了,精通Java已经不能算亮点.不能给自己加分了.可是事实真是这样吗? 对于语言的学习,我有一 ...

  6. 精通java益处_你真的精通Java吗?

    简历和自我介绍上经常能够读到"精通Java"这样的话,有人和我说,精通Java的人太多了,精通Java已经不能算亮点.不能给自己加分了.可是事实真是这样吗? 对于语言的学习,我有一 ...

  7. java精通时间_你真的精通 Java 吗?

    简历和自我介绍上经常能够读到" 精通 Java" 这样的话,有人和我说,精通 Java 的人太多了,精通 Java 已经不能算亮点.不能给自己加分了.可是事实真是这样吗? 对于语言 ...

  8. java 基础 笔试题_非常全面的java基础笔试题

    1.下列说法正确的是() (程序结构) A java程序的main方法必须写在类甩面 B java程序中可以有多个main方法 C.java程序中类名必须与文件名一样 D.JAVA程序的main方法中 ...

  9. java不是关键字_以下( )不是Java的关键字。_学小易找答案

    [单选题]放大电路的工作方式有甲类.乙类和甲乙类等,其中甲乙类放大器中放大管的导通角 . [单选题]以下标识符中不合法的是( ). [填空题]完成一个对象的复制后,如果在数值控制框中输入( ),会在复 ...

最新文章

  1. java lambda使用_Java 8 Lambda表达式的使用
  2. su: cannot set user id: Resource temporarily unavailable
  3. 社交网络初探——链路预测
  4. Taro+react开发(5)--tora项目开发安装
  5. 大数据的分析手段有哪几种
  6. django Form 效验
  7. 作为JavaScript的“超集”,感受一下TypeScript 的那些黑魔法
  8. linux中grep命令,Linux下grep命令详解
  9. 第一章 复数与复变函数
  10. 无线系列-无线通信系统组成
  11. ajax请求是宏任务还是微任务_ASP.NET Web API基础(04)---异步编程和跨域请求 - 高原秃鹫...
  12. 朴素和KMP匹配算法(java)
  13. Ping不通的原因分析
  14. Windows下svn使用教程
  15. win10安装包管理工具Chocolatey
  16. 个人整理 HTML全部标签总集,及用法
  17. Flannel网络原理(转载)
  18. 四大游戏编程网站,边玩边学Python
  19. 重磅!你们一直催的 PyEcharts教程来啦
  20. UML状态图画法参考博文整理

热门文章

  1. OpenCV与图像处理学习九——连通区域分析算法(含代码)
  2. 实验四51单片机并口实验
  3. JSTL-EL表达式 函数fn
  4. C++学习之路 | PTA乙级—— 1071 小赌怡情 (15 分)(精简)
  5. python的socket模块_python模块:socket模块
  6. java response.write_@ResponseBody与response.getWriter .write()区别
  7. LwIP应用开发笔记之四:LwIP无操作系统TFTP服务器
  8. Notepad++中的UTF-8无BOM格式编码
  9. [设计模式] ------ 单例模式
  10. 获取iOS任意线程调用堆栈(一)获取任意线程的调用栈地址列表