灵魂拷问:为什么 Java 字符串是不可变的?(1)

简介: 灵魂拷问:为什么 Java 字符串是不可变的?

在逛 programcreek 的时候,发现了一些精妙绝伦的主题。比如说:为什么 Java 字符串是不可变的?像这类灵魂拷问的主题,非常值得深思。


对于绝大多数的初级程序员来说,往往停留在“知其然不知其所以然”的层面上——会用,但要说底层的原理,可就只能挠挠头双手一摊一张问号脸了。


很长一段时间内,我也一直处于这种层面上。导致的局面就是,我在挖一些高深点的技术方案时,往往束手无策;在读一些高深点的技术文章时,往往理解不了作者在说什么。


借此机会,我就和大家一起,对“为什么 Java 字符串是不可变的”进行一次深入地研究。注意了,准备打怪升级了!


01、图文分析


来看下面这行代码。


String alita = "阿丽塔";


这行代码在字符串常量池中创建了一个内容为“阿丽塔”的对象,并将其赋值给了字符串变量 alita(存储的是字符串对象"阿丽塔"的引用)。如下图所示。


image.png


再来看下面这行代码。


String wanger = alita;


这行代码将字符串变量 alita 赋值给了字符串变量 wanger。这时候,wanger 和 alita 存储的是同一个字符串对象的引用。如下图所示。


image.png


再来看下面这行代码。


alita = "战斗天使".concat(alita);


这行代码将字符串“战斗天使”拼接在字符串变量 alita 的前面,并重新赋值给 alita。这个过程就比之前的复杂了。我们需要先来看看 concat() 方法做了什么,源码如下所示。


public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true);
}



可以看得出,"战斗天使".concat(alita) 这行代码会先在字符串常量池中创建一个新的字符串对象,内容为“战斗天使”,然后 concat() 方法会将其对应的字符数组和“阿丽塔”对应的字符数组复制到一个新的字符数组 buf 中,最后,再通过 new 关键字创建了一个新的字符串对象,并返回。如下图所示。


image.png


从上图中可以得出结论,alita 此时引用的是在堆中新创建的字符串对象。


相关文章
|
10天前
|
存储 安全 Java
Java灵魂拷问13个为什么,你都会哪些?
大家好,我是 V 哥。今天分享 13 个 Java 编程中的常见问题,包括 `BigDecimal` 的 `equals` 方法、`HashMap` 初始化容量、`Executors` 创建线程池等。这些问题都是 V 哥在日常编码中总结的经验,希望能帮助大家提升代码质量和性能。如果内容对你有帮助,请点赞关注,让我们在 Java 路上共同进步。
Java灵魂拷问13个为什么,你都会哪些?
|
3月前
|
安全 Java API
【Java字符串操作秘籍】StringBuffer与StringBuilder的终极对决!
【8月更文挑战第25天】在Java中处理字符串时,经常需要修改字符串,但由于`String`对象的不可变性,频繁修改会导致内存浪费和性能下降。为此,Java提供了`StringBuffer`和`StringBuilder`两个类来操作可变字符串序列。`StringBuffer`是线程安全的,适用于多线程环境,但性能略低;`StringBuilder`非线程安全,但在单线程环境中性能更优。两者基本用法相似,通过`append`等方法构建和修改字符串。
64 1
|
21天前
|
存储 安全 Java
Java零基础-字符串详解
【10月更文挑战第18天】Java零基础教学篇,手把手实践教学!
95 60
|
10天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
32 6
|
10天前
|
存储 Java 程序员
Java灵魂拷问13个为什么,你都会哪些?
【11月更文挑战第6天】本文回答了一些常见的 Java“灵魂拷问”,包括 Java 跨平台的原因、垃圾回收机制的作用、接口不能有实例变量的原因、字符串不可变的好处、异常处理机制的意义、类加载机制的双亲委派模型、多线程同步机制的重要性、重写方法访问修饰符的限制、包装类的存在意义、`equals()` 和 `hashCode()` 方法一起重写的原因、静态方法不能被重写的原因、`ArrayList` 扩容策略的权衡,以及 `final` 关键字的多种用途。
|
1月前
|
Java 数据库
案例一:去掉数据库某列中的所有英文,利用java正则表达式去做,核心:去掉字符串中的英文
这篇文章介绍了如何使用Java正则表达式从数据库某列中去除所有英文字符。
46 15
|
1月前
|
Java
JAVA易错点详解(数据类型转换、字符串与运算符)
JAVA易错点详解(数据类型转换、字符串与运算符)
50 4
|
2月前
|
Java 数据库
java小工具util系列1:日期和字符串转换工具
java小工具util系列1:日期和字符串转换工具
51 3
|
2月前
|
SQL Java 索引
java小工具util系列2:字符串工具
java小工具util系列2:字符串工具
18 2