千家信息网

为什么Java中String是不可变的

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,为什么Java中String是不可变的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。前言String 是 Java 语言非常基础和重
千家信息网最后更新 2026年11月03日为什么Java中String是不可变的

为什么Java中String是不可变的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

前言

String 是 Java 语言非常基础和重要的类,提供了构造和管理字符串的各种基本逻辑。它是典型的 Immutable 类,被声明成为 final class,所有属性也都是 final 的(hashCode方法除外)。也由于它的不可变性,类似拼接、裁剪字符串等动作,都会产生新的 String 对象。

一·什么是不可变对象

不可变对象是指一旦创建完成就不能再被修改的对象。也就说一旦一个对象被赋值了,这个对象的引用或者内部状态都不能被修改,对象所暴露的public方法不允许你修改

二·为什么使用不可变对象

使用不可变对象有四个优点:缓存,安全,同步,性能。使用不可变对象可以省去很多不必要的麻烦,而且很对场景下只能使用不可变对象(例如缓存结果)。对于可变对象传参或者赋值的时候,必须要copy这个可变参数的值,因为我们不知道这个可变对象的值何时会被修改。但如果使用的是final类型,就只需要copy这个变量的引用。因为Java确保了final类型的值不会被修改。

三·String的不可变

1.String的底层数据结构

String使用一个声明为final的字符数组value来存储值,value一旦赋值后所指向的地址就不能再被修改。虽然数组的值可以修改,但是String类本身并没有提供能够修改value数组值的方法。

    /** The value is used for character storage. */
private final char value[];

补充一下:当使用final修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变;但对于引用类型的变量,JDK保证的是变量指向的地址不会被改变(即指向的始终是同一个对象),至于地址的值(对象的值)是可以改变的。

2.字符串常量池

在前文中指出使用String这种不可变对象便于缓存,而jdk就为String提供了字符串常量池。字符串是最常使用的数据结构,缓存String并重复使用可以极大的节省Heap空间,因为相同的String变量指向了常量池中相同地址的值。例如以下代码只在字符串常量池中创建一个String对象

String string1 = "abcd";
String string2 = "abcd";
System.out.println(string1 == string2);
//代码输出结果为true

如图所示,如果String是可变的,那修改string1变量所指向的地址的内容,就会导致string2的内容也被修改了

3.安全

String在Java应用中被大量用于存储敏感信息(用户名,密码,URL等),也被JVM Class Loader用于加载类信息,因此十分有必要保证String的安全

void criticalMethod(String userName) {
// 1.安全检查
if (!isAlphaNumeric(userName)) {
throw new SecurityException();
}

// 2.更新DB
connection.executeUpdate("UPDATE Customers SET Status = 'Active' " +
" WHERE UserName = '" + userName + "'");
}

如上代码片段,方法传入一个userName的变量,第一步先检查改变量是否都是字母数字,然后执行sql 假设String是可变的,且方法已经执行过代码1还未执行代码2的时候,这时候上游调用方还持有参数userName的引用,如果调用方此时修改了userName的值,那就相当于混过了代码1出的安全检查。那么SQL注入的风险就会增加了

4.同步

"不可变"保证在并发编程模型中,不同Thread不能修改String的值,如果某个Thread修改了一个String值,这个值就会被缓存到StringPool中,也就是说对于String的引用是安全的。

5.Hashcode缓存

JDK提供了很多hash操作的数据结构:HashMap,HashTable,HashSet等,当在这些类上操作的时候,hashCode()方法就会被频繁的调用。"不可变"保证了String对象的值不会被修改,所以hash值也就不会被修改。对于不变的值就可以缓存起来以便之后调用hasCode()方法的时候就可以直接取出缓存中的值 JDK源码中String代码片段如下:

 /** Cache the hash code for the string */
private int hash; // Default to 0


/**
* Returns a hash code for this string. The hash code for a
* {@code String} object is computed as
*

* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
*

* using {@code int} arithmetic, where {@code s[i]} is the
* ith character of the string, {@code n} is the length of
* the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
public int hashCode() {
int h = hash;
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;
}

可以看到String对象有一个属性hash用于缓存hasCode()第一次计算的结果,之后调用hashCode()方法就直接从缓存中取出来

关于为什么Java中String是不可变的问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

对象 可变 缓存 变量 方法 代码 字符 安全 字符串 类型 地址 指向 常量 时候 保证 内容 数据 数据结构 数组 结构 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 为想互联网科技怎么样 科技赋能下的互联网金融 涨乐互联网科技 互联网是不是新科技 互联网金融与金融科技 互联网科技作文 成都互联网科技公司 深圳齐家互联网科技 善班互联网科技有限公司 大白互联网科技 深圳互联网科技怎么样 昭通云南众福互联网科技有限公司 常德市电业局互联网科技部 元气玛特互联网科技公司是外包吗 互联网科技快讯热点 新氧科技和美国互联网有关系吗 江苏互联网智能科技产品出厂价 互联网科技新闻 张家口科技产业互联网平台 安徽零酒互联网科技有限公司 A股互联网金融科技公司 互联网科技公司怎么样 一五八零互联网科技 科技赋能互联网健康 青海科技产业互联网发展 明优互联网科技有限公司 互联网企业科技类企业如何做账 半导体行业属于互联网高科技类吗 国产互联网科技公司 盐城市攀科互联网科技有限公司
0