news 2026/5/7 23:00:30

别再乱用 String 了!底层原理、常量池、拼接陷阱全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再乱用 String 了!底层原理、常量池、拼接陷阱全解析

做java开发,String是每天都在用的类,但是绝大部分人只停留在只会写、只会赋值,底层还不是很了解,很多人都有这样的疑惑:

  • 明明都是"abc",为什么==有时候相等、有时候不相等?
  • String 到底是不是可变的?为什么都说它不可变?
  • 循环里字符串拼接为什么不建议用+
  • String、StringBuilder、StringBuffer 到底该怎么选?
  • new String () 会创建几个对象?常量池到底有什么用?

一、什么是String?

String就是字符串,属于引用数据类型,但是用法很像基本数据类型,都可以直接赋值。

有三种创建String类型数据的方式:

1.直接用字符串赋值。

2.使用new String(),传字符串。

3.使用new String(),传字符数组。

很多人只会这么写,但不知道内存、常量池、底层结构差别巨大。

二、核心重点:为什么String是不可变的?

1.什么是不可变的?

字符串一旦建立,在这个字符串的基础上拼接和修改都是创建一个新的对象进行修改的。这里指的都是字符串不可变,但是String变量可以指向新的字符串,原来的字符串只是没有变量引用而已,依旧没有改变。

2.底层原理

JDK1.9 之前底层是private final char[ ]value

JDK1.9 之后优化为private final byte[ ] value

  • final:数组引用不能改
  • private:外部拿不到数组,改不了里面字符

所以对象本体内容 彻底无法修改。能变的只有外面的引用变量

3. 设计成不可变的好处

  1. 字符串常量池可以缓存复用,节省大量内存;
  2. 线程安全:不可变对象天然多线程安全;
  3. 哈希值固定,适合做 HashMap 键;
  4. 作为参数传递时更安全,不会被意外篡改。

三、字符串常量池(面试常问)

1.字面常量赋值:

String s1 = "java";

String s2 = "java";

System.out.println(s1 == s2); //true

通过==比较两个引用,比较的是在内存中的地址,输出结果是true,说明是s1和s2两个引用指向的是同一个字符串对象。

这说明通过字符串给引用变量赋值是要在常量池中寻找是否有此字符串常量

有:直接引用

无:现在常量池中创建这个字符串常量再引用

总之,只要是通过字符串常量赋值,指向的都是同一个字符串。这与Integer不一样,Integer只有部分值(0 - 127)是直接指向已有对象,超过区间是建立新的对象。

2.new String( )创建

  1. 先在常量池看有没有相同的字符串常量,没有就创建;
  2. 再在堆内存创建一个新 String 对象;
  3. 引用指向堆里的对象。所以地址不一样,==是 false。

3. 经典问题:new String ("abc") 创建几个对象?

  • 常量池没有:2 个(常量池 1 个 + 堆 1 个)
  • 常量池已有:1 个(只在堆创建)

四、字符拼接

1.普通拼接

String s = "a" + "b" + "c";

编译期会直接优化成String s = new String("abc"),放入常量池,效率很高。

2.循环拼接

String str = "";

for (int i = 0; i < 1000; i++) {

str += i; }

每一次+=都会生成新的 String 对象,大量创建废弃对象,浪费内存、效率极低。

循环拼接字符串,一律用 StringBuilder

  • 常量、少量拼接 →String
  • 单线程循环拼接 →StringBuilder
  • 多线程共享拼接 →StringBuffer

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/7 22:57:33

2.LeetCode 1089. 复写零——双指针解法学习笔记

目录 一、题目解析 二、算法原理&#xff1a;双指针法 步骤1&#xff1a;找最后一个“复写”的数 步骤2&#xff1a;处理边界情况 步骤3&#xff1a;从后往前复写 三、代码实现&#xff08;Java&#xff09; 四、复杂度分析 五、总结 OJ链接&#xff1a;https://leetco…

作者头像 李华
网站建设 2026/5/7 22:55:43

使用OpenClaw构建AI智能体时配置Taotoken作为提供商

使用OpenClaw构建AI智能体时配置Taotoken作为提供商 1. 准备工作 在开始配置之前&#xff0c;请确保已安装OpenClaw框架并完成基本环境搭建。同时需要在Taotoken平台获取有效的API Key&#xff0c;该Key可在Taotoken控制台的"API密钥管理"页面创建。建议为OpenClaw…

作者头像 李华
网站建设 2026/5/7 22:55:40

本土化赋能:Gitee如何重塑中国开发者的代码托管体验

在数字化转型加速的今天&#xff0c;代码托管平台已成为企业技术基础设施的重要组成部分。对于中国开发者而言&#xff0c;一个能够兼顾性能、合规与本地化支持的平台显得尤为重要。Gitee作为国内领先的代码托管服务&#xff0c;正通过其独特的本土化优势&#xff0c;为开发者提…

作者头像 李华
网站建设 2026/5/7 22:55:35

中国词元:构建自主AI生态的“云-端“协同战略

在全球化AI竞赛进入白热化的今天&#xff0c;中国科技企业正在探索一条独特的突围路径。当国际科技巨头通过封闭云帝国垄断AI基础设施时&#xff0c;中国产业界提出了"中国词元"的创新概念——通过整合本土模型、国产算力和绿色能源&#xff0c;构建自主可控的AI生态…

作者头像 李华
网站建设 2026/5/7 22:53:35

08-MLOps与工程落地——模型注册表与模型服务

模型注册表与模型服务&#xff08;MLflow Model Registry、Seldon Core&#xff09; 一、模型注册表概述 1.1 什么是模型注册表&#xff1f; import matplotlib.pyplot as plt from matplotlib.patches import Rectangle, FancyBboxPatch import warnings warnings.filterwarni…

作者头像 李华