当前位置: 首页 > news >正文

学习理解String的源代码

学习理解String的源代码

package java.lang;

代码块一

public final class Stringimplements Comparable<String>, CharSequence {// 1. 核心底层数组:存字符串每个字符private final char[] value;// 2. 哈希值缓存,默认0private int hash;// 空参构造:创建空字符串public String() {this.value = new char[0];}// 传入字符串构造方法public String(String original) {this.value = original.value;this.hash = original.hash;}

1.类声明

public final class Stringimplements Comparable<String>, CharSequence

1.public:公共类,项目任何地方都能用
2.final:不能被继承,防止别人篡改字符串底层
3.Comparable:自带比较功能,可以a.compareTo(b)
4.CharSequence:字符序列规范,属于字符类型

2 核心成员变量

// 1. 底层存储内容
private final char[] value;// 2. 哈希缓存
private int hash;

① private final char[] value
·字符串真正存数据的地方
·你写 abc,本质就是:['a','b','c']
·final:数组地址不能改 → 字符串不可变根源
·private:外面拿不到,安全
② private int hash
·用来存哈希值,默认初始值 = 0
·作用:算一次存起来,下次直接用,提高速度

3 空构造方法

public String() {this.value = new char[0];
}

·创建空字符串 ""
·底层给一个长度为 0 的空字符数组

4 拷贝构造(重点)

public String(String original) {this.value = original.value;this.hash = original.hash;
}
String s = new String("abc");

·直接复用传入字符串的 value 数组
·不复制数据,节省内存

代码块二

// 获取字符串长度public int length() {return value.length;}// 判断是否为空字符串public boolean isEmpty() {return value.length == 0;}// 根据下标获取单个字符public char charAt(int index) {if ((index < 0) || (index >= value.length)) {throw new StringIndexOutOfBoundsException(index);}return value[index];}

5 length () 方法

public int length() {return value.length;
}

·字符串长度 = 底层字符数组长度

·直接返回数组长度

6 isEmpty () 判断是否为空

public boolean isEmpty() {return value.length == 0;
}

·数组长度为 0 → 就是空字符串 ""

7 charAt () 根据下标取字符

public char charAt(int index) {if ((index < 0) || (index >= value.length)) {throw new StringIndexOutOfBoundsException(index);}return value[index];
}

·先判断下标是否越界
·越界直接报错
·没越界,直接返回数组对应位置字符

代码块三

// 重点:比较字符串内容public boolean equals(Object anObject) {// 1. 同一个对象,直接trueif (this == anObject) {return true;}// 2. 判断是不是String类型if (anObject instanceof String) {String anotherString = (String) anObject;int n = value.length;// 3. 长度不一样,直接falseif (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;}}return false;}// 重点:计算哈希值 + 缓存public int hashCode() {int h = hash;// 如果没计算过(h=0),开始计算if (h == 0 && value.length > 0) {char[] val = value;// 计算公式:h = 31 * h + 字符编码for (int i = 0; i < value.length; i++) {h = 31 * h + val[i];}hash = h; // 缓存保存,下次直接用}return h;}

8 equals () 源码

public boolean equals(Object anObject) {// 1. 判断是不是同一个对象(地址一样)if (this == anObject) {return true;}// 2. 判断是不是 String 类型if (anObject instanceof String) {String anotherString = (String) anObject;int n = value.length;// 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;}}return false;
}

执行流程:
this == anObject:地址相同 → 直接 true
不是 String 类型 → 直接 false
长度不一样 → 直接 false
一个一个字符对比
全部一样才返回 true
总结:
== 比地址
equals 比内容

9 hashCode () 哈希方法

public int hashCode() {int h = hash;// 如果没算过(h=0)并且字符串不为空if (h == 0 && value.length > 0) {char val[] = value;// 哈希计算公式for (int i = 0; i < value.length; i++) {h = 31 * h + val[i];}hash = h; // 把算好的值缓存保存}return h;
}

1.h =hash 先读取缓存

2.第一次使用 hash=0,进入计算

3.公式:

h=31*h+当前字符编码

4.算完赋值给hash缓存

5.下次调用直接拿缓存,不用重算

代码块四

// 截取字符串public String substring(int beginIndex) {return new String(value, beginIndex, value.length - beginIndex);}// 字符串拼接public String concat(String str) {int len = value.length;int otherLen = str.length();char[] buf = new char[len + otherLen];System.arraycopy(value, 0, buf, 0, len);System.arraycopy(str.value, 0, buf, len, otherLen);return new String(buf);}// 返回自身字符串public String toString() {return this;}
}

10 截取字符串 substring ( )

public String substring(int beginIndex) {return new String(value, beginIndex, value.length - beginIndex);
}

new String( char[] 原数组, int 起始下标, int 截取长度 )

·value
就是当前字符串底层的 char[] 原字符数组
·beginIndex
截取开始的位置(从第几个字符开始切)
·value.length - beginIndex
总长度 − 开始位置 = 要截取的字符个数

1.它不会动原来的字符数组 value
2.而是 new 一个全新的 String
3.把截取的内容放进新字符串里

11.字符串拼接 concat ( )

public String concat(String str) {int len = value.length;           // 原来字符串长度int otherLen = str.length();      // 要拼接的字符串长度char[] buf = new char[len + otherLen]; // 创建一个【新数组】System.arraycopy(value, 0, buf, 0, len); // 复制原字符串System.arraycopy(str.value, 0, buf, len, otherLen); // 复制拼接字符串return new String(buf); // 返回【新字符串】
}

1.先算总长度 = 原来长度 + 要拼接的长度
2.新建一个字符数组(更大的)
3.把两个字符串都复制进去
4.最后 new 一个新 String

11.toString( )

String 本身就是字符串,直接返回自己。

http://www.jsqmd.com/news/698914/

相关文章:

  • 2026年天津汽车后市场一站式综合体选购指南:买车、维保、改装、娱乐全搞定 - 年度推荐企业名录
  • 从毕业设计到实战:手把手教你用CAD和SolidWorks复现一个M24螺栓的电动扳手(附图纸)
  • 【苍穹外卖微服务改造】从单体到微服务:MinIO对象存储的优雅集成实践
  • 别再用 draw.io 拖拖拽拽了!这个开源项目让你用“说话“的方式画架构图
  • STM32CubeMX + FreeRTOS实战:手把手教你搞定串口printf打印(基于正点原子F429)
  • 如何用SharpKeys重新定义你的键盘:5分钟打造专属输入体验
  • 2026年天津遗嘱纠纷律所五星测评!自书遗嘱真伪认定,遗产分割高效维权 - 速递信息
  • 海边可以防晒伤防水防晒霜推荐,Leeyo 防晒,硬核防护告别晒伤泛红 - 全网最美
  • Docker + WASM 边缘计算落地实战:5大核心模块源码剖析(含v0.12.0 runtime 汇编级注释)
  • SMAPI安卓安装器:如何在手机上轻松安装星露谷物语MOD的完整指南
  • EspoCRM:打造企业级客户关系管理的开源解决方案
  • AB Download Manager:多线程下载加速与文件管理的终极解决方案
  • 显卡驱动深度清理实战:专业驱动卸载工具DDU应用方案
  • 厦门市翔安区寿苹电脑店:湖里电脑置换哪家好 - LYL仔仔
  • 天津波英废旧物资回收:天津工地废料回收电话多少 - LYL仔仔
  • Photoshop图层批量导出终极指南:告别手动操作,效率提升500% [特殊字符]
  • 3步搞定百度网盘提取码:baidupankey智能查询工具终极指南
  • # 67_MCU的几大分区
  • 量子投票:突破Arrow定理的社会选择新范式
  • 口碑好的轮毂维修公司
  • 如何用免费AI图像放大工具拯救你的模糊照片:Upscayl终极指南
  • 2026女性养雌激素口服品怎么选 - 品牌排行榜
  • 2025届毕业生推荐的六大降AI率平台实际效果
  • 保姆级教程:用uni-app + ECharts 5分钟搞定你的第一个数据可视化图表
  • Universal Android Debloater:无需Root的安卓设备终极清理方案
  • 晨芯阳HC8330,60V, 0.6A, 1.6MHz, 同步,降压直流/直流转换IC
  • 3分钟掌握Cookie Hacker:浏览器Cookie注入的完整指南
  • k8s中Calico无法连接到Kubernetes API Server
  • Mermaid Live Editor终极指南:免费在线图表编辑器快速上手教程
  • 如何快速制作AI动画:sd-webui-animatediff终极使用教程