Day11-Java中String的equals方法如何实现

简介: 笔记

在我们面试的时候经常会看到== 与 equals()的区别,我们在网上背一些这种题目的答案:


==:


如果是基本数据类型的比较,是值的比较

如果是引用类型的比较,⽐较的是两个引⽤是否指向相同的对象,也就是比较内存地址是否相同

equals():


equals 是比较内存地址上面的值是否相同

往往我们还是需要从源码的角度分析一下Java中String的equals方法如何实现。


首先我们都知道Java中所有的类都继承于Object这个类,在Object类中定义了一个equals的方法,equals的源码是这样写的:

15.png

可以看到,这个方法的初始默认行为是比较对象的内存地址值,一般来说,意义不大。所以在一些类库中被重写了(String、Integer等),在这些类当中equals有其自身的实现(一般都是用来比较对象的成员变量值是否相同),而不再是比较类在堆内存中的存放地址了。


因此,对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是内存中的存放位置的地址值,跟双等号(==)的结果相同;如果被复写,按照复写的要求来。


下面是关于String中equals() 方法的源码:

16.png

/**
 * String.equals()源码解析
 */
public boolean equals(Object anObject) {
    /**
     * 第一步:判断传入对象是否与当前对象的地址相同 this == anObject, 如果对象的地址相同, 可知对象相等, 返回 true
     * 看到下面这里行, 我们可以说 equals() 就是基于 == 来实现的
     */
    if (this == anObject) {
        return true;
    }
    /**
     * 第二步: 判断传递的参数 anObject 是否是 String, 如果不是直接返回 false
     */
    if (anObject instanceof String) {
        /**
         * 第三步: 如果 anObject 是 String 类型, 就强制转化为字符串, 然后判断当前对象与传递的对象的长度时候相同
         * 不相同则证明不等于, 返回 false
         */
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            /**
             *  第四步: 将两个对象转换为 char 数组,使用 while 循环逐一进行比较
             *  只有当 v1[i] == v2[i] 全部等于 true 时, 返回 true
             */
            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

判断传递的参数 anObject 是否是 String, 如果不是直接返回 false

第三步: 如果 anObject 是 String 类型, 就强制转化为字符串, 然后判断当前对象与传递的对象的长度时候相同,不相同则证明不等于, 返回 false

将两个对象转换为 char 数组,使用 while 循环逐一进行比较,只有当 v1[i] == v2[i] 全部等于 true 时, 返回 true

一句话:先比较地址,再比较内容,满足其中一个就可以返回true


测试代码

/**
 * @author :caizhengjie
 * @description :
 * @date :2021/7/25 20:09
 */
public class TestEquals {
    public static void main(String[] args) {
        // 字符串常量
        String s9 = "Hello";
        String s10 = "Hello";
        // 使用new关键字创建
        String s7 = new String("Hello");
        String s8 = new String("Hello");
        System.out.println(s7 == s9); // false
        System.out.println(s9 == s10); // true
        System.out.println(s7 == s8); // false
        System.out.println("--------------");
        System.out.println(s7.equals(s9)); // true
        System.out.println(s7.equals(s8)); // true
    }
}

文字解析:


从上面的运行结果可见,s7和s8指的是不同对象, s9和s10指向的是相同对象。

Java中的不可变字符串String常量,采用字符串池(String Pool)管理技术,字符串池是 一种字符串驻留技术。采用字符串常量赋值时会在字符串池中查 找"Hello"字符串常量,如果已经存在把引用赋值给s9,否则创建"Hello"字符串对象,并放到池中。根 据此原理,可以推定s10与s9是相同的引用,指向同一个对象。但此原理并不适用于new所创建的字符 串对象,它并没有放到字符串池中。s7和s8是不同的引用,指向不同的对象。


图解:20.png


目录
打赏
0
0
0
0
12
分享
相关文章
Java快速入门之数组、方法
### Java快速入门之数组与方法简介 #### 一、数组 数组是一种容器,用于存储同种数据类型的多个值。定义数组时需指定数据类型,如`int[]`只能存储整数。数组的初始化分为静态和动态两种: - **静态初始化**:直接指定元素,系统自动计算长度,如`int[] arr = {1, 2, 3};` - **动态初始化**:手动指定长度,系统给定默认值,如`int[] arr = new int[3];` 数组访问通过索引完成,索引从0开始,最大索引为`数组.length - 1`。遍历数组常用`for`循环。常见操作包括求和、找最值、统计特定条件元素等。
Java快速入门之类、对象、方法
本文简要介绍了Java快速入门中的类、对象和方法。首先,解释了类和对象的概念,类是对象的抽象,对象是类的具体实例。接着,阐述了类的定义和组成,包括属性和行为,并展示了如何创建和使用对象。然后,讨论了成员变量与局部变量的区别,强调了封装的重要性,通过`private`关键字隐藏数据并提供`get/set`方法访问。最后,介绍了构造方法的定义和重载,以及标准类的制作规范,帮助初学者理解如何构建完整的Java类。
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
31 9
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
40 12
Java 方法注释:规范、实用和高质量的写法
本文深入探讨了如何编写高质量的 Java 方法注释
35 11
Java 中的 String Pool 简介
本文介绍了 Java 中 String 对象及其存储机制 String Pool 的基本概念,包括字符串引用、构造方法中的内存分配、字符串文字与对象的区别、手工引用、垃圾清理、性能优化,以及 Java 9 中的压缩字符串特性。文章详细解析了 String 对象的初始化、内存使用及优化方法,帮助开发者更好地理解和使用 Java 中的字符串。
Java 中的 String Pool 简介
java 为什么 String 在 java 中是不可变的?
本文探讨了Java中String为何设计为不可变类型,从字符串池的高效利用、哈希码缓存、支持其他对象的安全使用、增强安全性以及线程安全等方面阐述了不可变性的优势。文中还通过具体代码示例解释了这些优点的实际应用。
java 为什么 String 在 java 中是不可变的?
|
1月前
|
java中“==”和equals,究竟比的是什么
java中“==”和equals,究竟比的是什么
59 4
Java 11 的String是如何优化存储的?
本文介绍了Java中字符串存储优化的原理和实现。通过判断字符串是否全为拉丁字符,使用`byte`代替`char`存储,以节省空间。具体实现涉及`compress`和`toBytes`方法,前者用于尝试压缩字符串,后者则按常规方式存储。代码示例展示了如何根据配置决定使用哪种存储方式。

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等