String类的equals()的作用和源代码解读

文章目录

目录

文章目录

前言

一、equals()方法是怎么来的?

二、equals()的核心作用与设计背景

三、String.equals()源代码深度解析(基于 JDK 8)

           关键步骤的设计逻辑与优化点

四、特殊场景与注意事项

五、equals()的性能特性

总结


前言

        在 Java 中,String 类的 equals() 方法是用于比较两个字符串的内容是否相等的重要方法,该方法接收一个 Object 类型的参数 anObject,返回一个布尔值,表示当前 String 对象与传入对象的内容是否相等。在 Java 中,String类的equals()方法是重写自Object的核心方法,其设计目标是精确判断两个字符串的字符序列是否完全一致。相较于Object类默认的 “引用地址比较”,String.equals()实现了 “内容比较”,这一特性使其成为日常开发中最常用的方法之一。下面我们从设计逻辑、源代码细节、特殊场景等方面进行深度解读。

一、equals()方法是怎么来的?

  • 首先我们肯定知道equals()方法源自于Object类,我们知道Java 中的所有类都直接或间接继承自Object类,equals()方法就是Object类中的一个方法。Object类是 Java 类层次结构的根类,它为所有类提供了一些基本的通用方法,equals()就是其中之一,用于对象之间的比较。在Object类中,equals()方法的默认实现是比较两个对象的内存地址,即判断两个引用是否指向同一个对象。

二、equals()的核心作用与设计背景

  1. 核心作用
    用于比较两个字符串的字符内容是否完全相同,包括字符序列、长度、大小写(大小写敏感)等。例如:

    • "hello".equals("hello") → true(内容完全一致)
    • "hello".equals("Hello") → false(大小写不同)
    • "hello".equals("hell") → false(长度不同)
  2. Object.equals()的区别

  3. Object类的equals()默认比较对象引用地址(等价于==),源码为:
    public boolean equals(Object obj) {
        return (this == obj); // 仅判断是否为同一个对象
    }

    String类重写后,改为比较字符内容,更符合字符串 “值相等” 的业务需求。

三、String.equals()源代码深度解析(基于 JDK 8)

String类的equals()方法源代码如下,其逻辑经过多层优化,兼顾正确性与效率:

public boolean equals(Object anObject) {
    // 步骤1:判断是否为同一个对象(引用地址相同)
    if (this == anObject) {
        return true;
    }
    // 步骤2:判断参数是否为String类型(非String直接返回false)
    if (anObject instanceof String) {
        String anotherString = (String)anObject; // 强制类型转换
        int n = value.length; // 当前字符串的长度(value是存储字符的底层数组)
        // 步骤3:比较字符串长度(长度不同则内容一定不同)
        if (n == anotherString.value.length) {
            char v1[] = value; // 当前字符串的字符数组
            char v2[] = anotherString.value; // 目标字符串的字符数组
            int i = 0;
            // 步骤4:逐个比较字符(直到所有字符相同或发现差异)
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    // 非String类型或其他情况,返回false
    return false;
}
        关键步骤的设计逻辑与优化点
  1. 步骤 1:先比较引用地址(this == anObject

    • 若两个字符串引用指向同一个对象(内存地址相同),则内容必然相同,直接返回true
    • 这是最高效的短路判断,避免后续所有操作(尤其长字符串的字符比较),时间复杂度为O(1)
String s1 = "abc";
String s2 = s1;
s1.equals(s2); // 触发步骤1,直接返回true

步骤 2:判断参数类型(anObject instanceof String

    • 仅当参数是String类型时才继续比较,否则直接返回false
    • 为什么用instanceof
      • instanceof会自动处理null:若anObjectnullinstanceof返回false,避免NullPointerException(无需单独写if (anObject == null)判断)。
      • 确保类型匹配:例如"abc".equals(new StringBuilder("abc"))会返回false(因StringBuilder不是String类型)。
  1. 步骤 3:比较字符串长度(n == anotherString.value.length

    • String底层用private final char value[]数组存储字符,value.length即字符串长度。
    • 若两个字符串长度不同,内容一定不同,直接返回false,避免无效的字符遍历(优化点:减少O(n)操作)。
  2. 示例:
    "abcd".equals("abc") → 长度 4≠3,步骤 3 直接返回false

  3. 步骤 4:逐个比较字符(v1[i] != v2[i]

    • 若长度相同,遍历两个字符数组,逐个比较对应索引的字符。
    • 一旦发现不同字符(如v1[2] != v2[2]),立即返回false(提前退出,减少不必要的比较)。
    • 若所有字符都相同(循环结束),返回true
    • 字符比较基于Unicode 编码值(例如'a'的编码是 97,'A'是 65,因此大小写不同会返回false)。
    • 循环中n-- != 0的写法:先判断n是否为 0,再自减,等价于从索引0遍历到n-1

四、特殊场景与注意事项

  1. null比较

    • String.equals(null)返回false(因null instanceof Stringfalse),不会抛异常。
    • 反例:若参数在前(如null.equals("abc")),会直接抛NullPointerException,因此推荐写法是常量在前
  2. 空字符串""的比较

    空字符串的value数组长度为 0,因此:
    • "" equals(" ") → false(后者长度为 1,且字符为空格)。
    • "" equals("") → true(长度相同,且无字符差异)。
  3. 与其他类型对象的比较

    若参数不是String类型(如StringBufferObject等),即使内容相同,equals()也返回false
    • String s = "abc";
      StringBuffer sb = new StringBuffer("abc");
      s.equals(sb); // false(sb不是String类型)
      
  4. 大小写敏感问题

    equals()严格区分大小写,若需忽略大小写,应使用equalsIgnoreCase()
    • "Hello".equals("hello"); // false
      "Hello".equalsIgnoreCase("hello"); // true
      
  5. 字符串常量池的影响

    对于字符串常量(如"abc"),JVM 会将其存入常量池,相同内容的常量会指向同一对象,此时==也会返回true
    • String s1 = "abc";
      String s2 = "abc";
      s1 == s2; // true(常量池同一对象)
      s1.equals(s2); // true(内容相同)
      
    • 但通过new String("abc")创建的对象会在堆中生成新实例,此时==返回false,但equals()仍返回true

五、equals()的性能特性

  • 时间复杂度
    • 最好情况:O(1)(步骤 1、2、3 直接返回,无需比较字符)。
    • 最坏情况:O(n)(需比较所有n个字符,如两个完全相同的长字符串)。
  • 优化逻辑
    方法通过 “先判断引用→再判断类型→再判断长度→最后比较字符” 的顺序,尽可能早地排除不相等的情况,减少无效计算,体现了高效的设计思路。

总结

   String.equals()是 Java 中 “内容相等” 判断的标准实现,其核心逻辑是通过多层优化的比较步骤,精确判断两个字符串的字符序列是否一致。理解其源代码不仅能掌握字符串比较的细节,还能学习到 “短路判断”“类型校验” 等代码优化思想,对重写其他类的equals()方法也有借鉴意义。

好了,今天依旧是深蹲不写BUG,我们一起努力!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值