0

0

在Java里String为什么设计成不可变_Java字符串设计原理解析

P粉602998670

P粉602998670

发布时间:2026-02-05 10:14:03

|

742人浏览过

|

来源于php中文网

原创

String不可变指内容不可修改,本质是“内容锁死”:final类、私有不可变底层数组、所有方法返回新对象;常量池共享、HashMap键稳定、多线程安全均依赖此特性。

在java里string为什么设计成不可变_java字符串设计原理解析

String不可变,本质是“内容锁死”,不是“变量锁死”

很多人看到 str = str + "a" 就以为字符串被修改了,其实只是变量 str 指向了一个新对象;原来的字符串对象(比如 "Hello")在堆里纹丝不动,哪怕没人再引用它,也得等GC来收——这才是“不可变”的真实含义。

关键实现靠三重防护:final class String 阻止继承、private final char[] value(JDK8及之前)或 private final byte[] value(JDK9+)封住底层数组引用、所有 public 方法(如 substring()replace())全部返回新对象,绝不碰原数组一个字节

  • 别信“final 数组就安全”这种说法:final int[] arr = {1} 仍可改 arr[0] = 2;String 安全靠的是封装 + 不暴露 value + 所有方法绕开原数组操作
  • 反射强行修改 value 是可能的(比如用 UnsafeField.setAccessible(true)),但这属于破坏 JVM 合约,生产环境严禁,且 JDK9+ 的 byte[] + 编码压缩让反射更难生效

字符串常量池(String Pool)为什么必须依赖不可变性

当你写 String a = "abc"; String b = "abc";,JVM 让 ab 共享同一个对象——这省内存、提速度。但如果 "abc" 可被修改,a.toUpperCase() 一调,b 看到的就变成 "ABC",逻辑直接崩坏。

常量池不是“功能开关”,而是不可变性的必然产物:只有内容永不改变,多个引用共享才敢放心。

立即学习Java免费学习笔记(深入)”;

  • 使用 new String("abc") 会绕过常量池,在堆里新建对象,== 比较必为 false
  • intern() 是手动“拉回”常量池的补救手段,但代价是字符串首次入池时要查表,高频调用反而拖慢性能
  • JDK7 把常量池从永久代移到堆内存后,intern() 行为更可控,但依然不建议在循环里滥用

HashMap 的 key 为什么非得用不可变对象

如果 String 可变,你把 "user" 当 key 存进 HashMap,之后又把它改成 "USER",它的 hashCode() 就变了——但 HashMap 还按旧 hash 值找桶,结果 map.get("user") 返回 null,数据“消失”了。

Felo Search
Felo Search

一个全新的多语言AI搜索引擎

下载

String 的 hashCode() 方法内部缓存了结果:private int hash,首次计算后就不再重算。这个优化只在不可变前提下成立。

  • 自定义类作 key 时,务必保证 hashCode()equals() 所依赖的字段不可变,否则一样掉坑里
  • 别为了“节省对象创建”而复用 StringBuilder 拼出的字符串去当 key:虽然内容一样,但它是新对象,没问题;但若你把它转成 String 后又用反射改了内容……那就自己挖坑自己跳

多线程场景下,不可变性省掉的不是代码,是排查时间

一个 public static final String CONFIG_PATH = "/etc/app.conf" 被十个线程同时读,完全不用加锁、不用 volatile、不用 synchronized。因为没人能改它——连“改”的入口都被语言层堵死了。

换成可变对象,哪怕只读不写,你也得确认:有没有其他线程正在调用它的 setter?有没有子类偷偷覆写了行为?有没有某个工具类在背后做了 in-place 修改?

  • 类加载器用字符串定位类名(如 "java.lang.Object"),如果这段字符串中途被篡改,可能加载恶意类,这是 JVM 安全模型的基石之一
  • 日志框架中传递的 String 格式模板(如 "User {} logged in from {}")也是靠不可变性确保打印时不被并发修改导致格式错乱

真正容易被忽略的点是:不可变性不是“语法糖”,它是贯穿 JVM 内存模型、安全机制和集合设计的底层契约。一旦你开始用反射、Unsafe 或 JNI 去绕过它,后续所有基于该假设的优化(常量池、hash 缓存、线程安全共享)都会失效——而这种失效往往不会报错,只会悄悄出 bug。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

564

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

238

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

560

2024.03.01

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1506

2023.10.24

字符串常量的表示方法
字符串常量的表示方法

字符串常量的表示方法:1、使用引号;2、转义字符;3、多行字符串;4、原始字符串;5、字符串连接;6、字符串字面量和对象;7、编码问题。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

140

2023.12.26

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

381

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

213

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1506

2023.10.24

微信网页版文件传输助手教程合集
微信网页版文件传输助手教程合集

本专题整合了微信网页版文件传输助手教程、入口等等内容,阅读专题下面的文章了解更多详细内容。

15

2026.02.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.2万人学习

C# 教程
C# 教程

共94课时 | 8.6万人学习

Java 教程
Java 教程

共578课时 | 57.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号