前言

==和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 640 求解方程(计算器的加减法计算)

    640. 求解方程 求解一个给定的方程,将x以字符串"x=#value"的形式返回.该方程仅包含'+',' - '操作,变量 x 和其对应系数. 如果方程没有解,请返回" ...

  2. Java实现 蓝桥杯 算法提高 求arccos值

    算法提高 7-2求arccos值 时间限制:10.0s 内存限制:256.0MB 提交此题 问题描述 利用标准库中的cos(x)和fabs(x)函数实现arccos(x)函数,x取值范围是[-1, 1 ...

  3. java实现第六届蓝桥杯立方体自身

    立方变自身 题目描述 观察下面的现象,某个数字的立方,按位累加仍然等于自身. 1^3 = 1 8^3 = 512 5+1+2=8 17^3 = 4913 4+9+1+3=17 - 请你计算包括1,8, ...

  4. Navicat 连接远程服务器端MySQL

    Navicat是一个很好的操作各种数据库的图形化工具,我用它在本地连接过MySQL.SQL Server.SQLite,用它操作数据库确实非常方便.快捷,再搭配SQL语句,是一个很好的选择了. 废话不 ...

  5. [apue] epoll 的一些不为人所注意的特性

    之前曾经使用 epoll 构建过一个轻量级的 tcp 服务框架: 一个工业级.跨平台.轻量级的 tcp 网络服务框架:gevent 在调试的过程中,发现一些 epoll 之前没怎么注意到的特性. a) ...

  6. 杨辉三角 js 练习

    //打印杨辉三角a[[],[],[]] function fn(n){ //i=0 1 2 3.. var a = new Array(n); //行 1 2 3 4.. 创建二维数组. for(va ...

  7. jetty 启动项目在pom.xml 的配置

    <build> <finalName>${artifactId}</finalName> <resources> <resource> &l ...

  8. window.open打开新的独立页面

    如下所示的代码: window.open('xxxxx.html', '_blank', 'height=100, width=400, top=0, left=0, toolbar=no, menu ...

  9. Nice Jquery Validator 自定义规则

    规则定义方式 (1). 正则 适用于使用单个正则能搞定的验证. // 使用数组包裹正则和错误消息,规则不通过时提示该消息 mobile: [/^1[3458]\d{9}$/, '请检查手机号格式'] ...

  10. Python流程控制语句详解

    1.程序结构 计算机在解决问题时,分别是顺序执行所有语句.选择执行部分语句.循环执行部分语句,分别是:顺序结构.选择结构.循环结构.如下图: 2.选择语句 2.1最简单的if语句 Python使用保留 ...