前言

==和equals是我们面试中经常会碰到的问题。那么它们之间有什么联系和区别呢?今天我们就来聊聊吧!

问题

这里先抛出一些比较典型笔试问题:

int x = 10;
int y = 10;
String str1 = new String("abc");
String str2 = new String("abc");
String str3 = "abc";
String str4 = "abc";
System.out.println(x == y); // 输出?
System.out.println(str1 == str2); // 输出?
System.out.println(str1.equals(str2)); // 输出?
System.out.println(str3 == str4); // 输出?
System.out.println(str1 == str3); // 输出?
System.out.println(str1.equals(str3)); // 输出? Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);// 输出?
System.out.println(f3 == f4);// 输出?

正文

​ 我们通常就是说"=="用来判断两个变量之间的的值是否相等。变量又分为基本数据类型变量和引用类型。如果是基本数据类型的变量直接比较值而引用类型要比较对应的引用的内存的首地址。而equals方法 通俗来说就是用来比较两个对象长得是否一样。判断两个对象的某些特征(内容)是否一样。实际上就是调用对象的equals方法进行比较。那么我们来看看equals方法吧!

​ equals方法其实是属于Object类的方法。因为Object类是所有类的直接或间接父类,也就是说所有的类中的equals()方法都继承自Object类,而通过源码我们发现,Object类中equals()方法底层实现其实就是是"=="号。

public boolean equals(Object obj) {
return (this == obj);
}

那么,在所有没有重写equals()方法的类中,调用equals()方法其实和使用"=="号的效果一样,也是比较的对象地址值,然而,Java提供的所有类中,绝大多数类都重写了equals()方法,重写后的equals()方法一般都是比较两个对象的值,比如String类,Date类,基本数据类型的包装类等。可以看哈String类的源码:

    public boolean equals(Object var1) {
if (this == var1) {
return true;
} else {
if (var1 instanceof String) {
String var2 = (String)var1;
int var3 = this.value.length;
if (var3 == var2.value.length) {
char[] var4 = this.value;
char[] var5 = var2.value;
for(int var6 = 0; var3-- != 0; ++var6) {
if (var4[var6] != var5[var6]) {
return false;
}
}
return true;
}
}
return false;
}
}

解决

看了上面的描述,相信你可以做对或者回答起大多数这类的问题。但是还需要注意以下两点:

String str3 = "abc";
String str4 = "abc";
System.out.println(str3 == str4); // 输出true
  • 这里为什么会是true呢?按理说str3和str4是两个对象,"=="比较的是地址,应该会是false才对。如果你是这么想的,那你就不是很了解String类。String类,我们都知道它是不可变的字符序列,存储在常量池中,所以当你声明了一个str3="abc"时,就会在常量池中开辟一个内存空间来存放"abc",下次再声明时,就会在常量池中去找,有,就直接把当前地址赋给变量,没有,就再创建。因此,此处的str3和str4是指向的同一个内存地址。
Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);// 输出true
System.out.println(f3 == f4);// 输出false
  • 看到上面的答案是不是感到十分的诧异。其实这里隐藏着一个知识点。就是包装类的缓存问题。下面简单描述一下:

    整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理。当然其目的就是提高效率。

    缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

    此处以Integer类为例,源码参考:

    public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i); // 超过范围就是new的Integer对象
    }

    这段代码中我们需要解释下面几个问题:

    1. IntegerCache类为Integer类的一个静态内部类,仅供Integer类使用,作用就是初始化数组cache的,这个过程会在类加载时完成。感兴趣可以去看哈源码,这里就不再粘贴了。
    2. 一般情况下 IntegerCache.low为-128,IntegerCache.high为127,IntegerCache.cache为内部类的一个静态属性。

看到这,相信你对上面抛出的问题,已经可以迎刃而解。答案参考:

		int x = 10;
int y = 10;
String str1 = new String("abc");
String str2 = new String("abc");
String str3 = "abc";
String str4 = "abc";
System.out.println(x == y); // 输出true
System.out.println(str1 == str2); // 输出false
System.out.println(str1.equals(str2)); // 输出true
System.out.println(str3 == str4); // 输出true
System.out.println(str1 == str3); // 输出false
System.out.println(str1.equals(str3)); // 输出true Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);// 输出true
System.out.println(f3 == f4);// 输出false

公众号:良许Linux

有收获?希望老铁们来个三连击,给更多的人看到这篇文章

谈谈javaSE中的==和equals的联系与区别的更多相关文章

  1. Java中BigDecimal的equals与compareTo的区别

          有个是否为零的判断[BigDecimal.ZERO.equals(ratio)]我用了BigDecimal的equals方法,结果,判断失败,因此特地分析一下equals与compareT ...

  2. 【原创】Java和C#下String类型中的==和equals的原理与区别

    一.Java下 1.几个例子 public static void main(String[] arge) { String str1 = new String("1234"); ...

  3. java 中字符串比较equals()和equalsIgnoreCase()的区别

    1.使用equals( )方法比较两个字符串是否相等 boolean equals(Object str) 这里str是一个用来与调用字符串(String)对象做比较的字符串(String)对象. 如 ...

  4. JAVA中字符串比较equals()和equalsIgnoreCase()的区别

    1.使用equals( )方法比较两个字符串是否相等(区分大小写) 2.使用equalsIgnoreCase( )方法比较两个字符串是否相等(不区分大小写) boolean equalsIgnoreC ...

  5. 谈谈Python中列表、元组和数组的区别和骚操作

    一.列表(List) 1.列表的特点 列表是以方括号“[]”包围的数据集合,不同成员以“,”分隔.如 L = [1,2,3], 列表a有3个成员. 列表是可变的数据类型[可进行增删改查],列表中可以包 ...

  6. 谈谈 UI 中, Padding 和 Margin 有什么区别?

    android:padding 和 android:layout_margin 的区别,其实概念很简单,padding 是站在父 view 的角度描述问题,它规定它里面的内容必须与这个父 view 边 ...

  7. java中hashcode()和equals()的详解

    今天下午研究了半天hashcode()和equals()方法,终于有了一点点的明白,写下来与大家分享(zhaoxudong 2008.10.23晚21.36). 1. 首先equals()和hashc ...

  8. java中的==、equals()、hashCode()源码分析

    转载自:http://www.cnblogs.com/xudong-bupt/p/3960177.html 在Java编程或者面试中经常会遇到 == .equals()的比较.自己看了看源码,结合实际 ...

  9. JavaSE中Collection集合框架学习笔记(2)——拒绝重复内容的Set和支持队列操作的Queue

    前言:俗话说“金三银四铜五”,不知道我要在这段时间找工作会不会很艰难.不管了,工作三年之后就当给自己放个暑假. 面试当中Collection(集合)是基础重点.我在网上看了几篇讲Collection的 ...

随机推荐

  1. Java实现 LeetCode 105 从前序与中序遍历序列构造二叉树

    105. 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中 ...

  2. Java GUI 窗体事件

    import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; publi ...

  3. Java实现 洛谷 P1583 魔法照片

    import java.util.*; class Main{ public static void main(String[] args) { Scanner in = new Scanner(Sy ...

  4. java实现不连续处断开

    不连续处断开 下列代码运行结果为: 12345 23456 89 23456789 即把一个串从数字不连续的位置断开.试完善之. String s = "123452345689234567 ...

  5. Java实现第九届蓝桥杯缩位求和

    缩位求和 题目描述 在电子计算机普及以前,人们经常用一个粗略的方法来验算四则运算是否正确. 比如:248 * 15 = 3720 把乘数和被乘数分别逐位求和,如果是多位数再逐位求和,直到是1位数,得 ...

  6. java实现第四届蓝桥杯猜灯谜

    猜灯谜 题目描述 A 村的元宵节灯会上有一迷题: 请猜谜 * 请猜谜 = 请边赏灯边猜 小明想,一定是每个汉字代表一个数字,不同的汉字代表不同的数字. 请你用计算机按小明的思路算一下,然后提交&quo ...

  7. Oracle RMAN各类压缩算法对比测试

    1.背景概述 2.本次测试环境基本信息 3.测试步骤 3.1. 使用BCO进行压缩备份 3.2. 不使用压缩备份 3.3. 使用ACO中LOW级别进行压缩备份 3.4. 使用ACO中MEDIUM级别进 ...

  8. keras搭建神经网络快速入门笔记

    之前学习了tensorflow2.0的小伙伴可能会遇到一些问题,就是在读论文中的代码和一些实战项目往往使用keras+tensorflow1.0搭建, 所以本次和大家一起分享keras如何搭建神经网络 ...

  9. 关于echart的x轴固定为0-24小时显示一天内的数据

    需求: echart折线图横坐标x轴固定显示为0-1-2-3-...-23-24一共24小时的数据. 根据需求,我在网上以及echart官网,发现x轴无论type是类目轴还是时间,都是自动处理的,尤其 ...

  10. Excel怎样根据出生日期,快速计算出其年龄呢?

    问题:怎样根据出生日期,快速计算出其年龄呢? 方法:DATEDIF函数 Step1:在编辑栏中输入公式:=DATEDIF(E2,TODAY(),”Y”),按回车键. Step2:用鼠标向下拖拽复制公式 ...