Java 中 String 和 StringBuffer 的区别2025年8月4日 | 阅读 7 分钟 在 Java 中,String 是不可变的,这意味着一旦创建,我们就无法更改它。这使得它在频繁修改文本时效率较低。相反,StringBuffer 是可变的且线程安全的,非常适合需要频繁更改的字符串,尤其是在多线程环境中。 Java 字符串在 Java 中,String 用于表示字符序列,但它们在可变性以及处理修改的方式上存在显著差异。 ![]() String 的特性1. 不可变性: String 对象在 Java 中最关键的特性是它们是不可变的。这意味着当我们创建了一个 String 对象后,它的内容就不能被更改。 当对 String 执行诸如连接或子字符串之类的操作时,会创建一个全新的 String 对象,其中包含修改后的内容。然而,原始的 String 对象在内存中保持不变。 示例 它是如何工作的? String 对象内部使用一个 char 数组来存储字符序列。由于它们是不可变的,这个 char 数组在创建后基本上是固定大小和内容的。 2. 线程安全性(同步): 由于 String 对象是不可变的,它们本质上是线程安全的。多个线程可以并发访问它们,而不会有数据不一致的风险,因为它们的状态无法更改。 3. String 性能: 对于涉及频繁修改的操作,String 通常效率较低。每次修改都会创建一个新的 String 对象。这会导致更多的内存分配和更多的垃圾回收工作。当字符串是常量或很少修改时,它是高效的。 4. 内存使用: String Pool 存储字符串字面量。如果已存在具有相同值的 String 对象,它会通过重用现有对象来优化内存使用。 使用 new String() 创建的 String 对象存储在通用堆内存中,不属于 String Pool。 5. 主要用例: 当一个字符序列是常量且不会被修改时,使用 String。非常适合表示固定文本,例如名称、标签或枚举值。它们在多线程环境中很有用,因为不可变性是安全性的优势。 String 示例编译并运行输出 Original String: Hello Memory address (approx. hash): 622488023 After Concatenation (originalString + " World"): Hello World Memory address of concatenatedString: 2124308362 Original String after concatenation: Hello Memory address of originalString (still the same): 622488023 解释 当执行 originalString + " World" 时,会在内存中创建一个新的 String 对象 "Hello World"。originalString 本身仍然指向原始的 "Hello" 对象。 只有当我们重新赋值 originalString = originalString + " Java" 时,originalString 变量才会指向一个包含 "Hello Java" 的新 String 对象。如果没有任何其他引用指向它们,旧的 "Hello" 和 "Hello World" 对象可能会符合垃圾回收的条件。 注意:您在此程序中可能会得到不同的内存地址。Java StringBuffer在 Java 中,String 用于表示字符序列,但它们在可变性以及处理修改的方式上存在显著差异。 ![]() StringBuffer 的特性1. StringBuffer 可变: StringBuffer 对象是可变的。诸如追加、插入或删除字符之类的操作会修改内存中的现有对象,而不是创建新对象。 示例 它是如何工作的? StringBuffer 使用内部 char 数组,允许动态扩展。当其当前容量不再足够时,会在内部创建一个新的、更大的数组,并将字符数据传输过去,从而确保在同一个 StringBuffer 对象内进行高效的内容修改。如图所示,StringBuffer 对象包含长度(当前大小)和容量(分配的空间),允许它增长。 2. 线程安全:一次只有一个线程可以访问 StringBuffer 实例的方法。它可以在多线程环境中防止数据损坏。这会带来性能上的开销。 3. StringBuffer 的性能: 对于涉及频繁修改的场景,StringBuffer 比 String 更高效。由于它修改现有对象,因此避免了创建许多新对象的开销。 4. 然而,由于其同步特性,在单线程环境中它比 StringBuilder 略慢,因为有获取和释放锁的开销。 5. StringBuffer 的内存使用: StringBuffer 对象始终存储在通用堆内存中。它们不使用 String Pool。 6. StringBuffer 的主要用例:当字符序列需要频繁修改且需要线程安全时使用。 StringBuffer 示例编译并运行输出 Original StringBuffer: Hello Memory address (approx. hash): 622488023 After append(" World"): Hello World Memory address of sb (still the same): 622488023 After insert(6, "Beautiful "): Hello Beautiful World Memory address of sb (still the same): 622488023 解释 在所有修改操作(追加、插入、删除、反转)中,StringBuffer 对象 sbuff 本身会被直接修改。我们可以观察到它的 System.identityHashCode()(内存地址的大致表示)在这些操作中保持不变,这表明对于这些修改,堆中没有创建新对象。只有当我们显式调用 sbuff.toString() 时,才会根据 StringBuffer 的当前内容创建一个新的 String 对象。 注意:您在此程序中可能会得到不同的内存地址。String 与 StringBuffer 的对比
String 的用法
StringBuffer 的用法
结论String 和 StringBuffer 的主要区别对于有效的 Java 字符序列处理至关重要。String 对象是不可变的,这使得它们天然线程安全,并且非常适合常量文本。相比之下,对 String 进行频繁修改会导致性能开销,因为每次操作都会创建一个新对象。 String 和 StringBuffer 选择题1) Java 中 String 对象的主要特性是其 __________,这意味着一旦创建,其内容就不能被更改。
答案:c) 解释:不可变意味着“不可更改”。一旦用特定值创建了一个 String 对象,该值就不能被更改。任何看似修改 String 的操作实际上都会创建一个新的 String 对象。 2) 当一个 String 对象被修改时(例如,通过连接),会在内存中创建一个 __________ String 对象。
答案:a) 解释:由于 String 是不可变的,任何“修改”,如连接 (+) 操作,都不会改变原始对象。相反,会生成一个全新的 String 对象,其中包含组合内容。 3) StringBuffer 对象是 _________ 的,允许 append() 和 insert() 等操作修改内存中的现有对象。
答案:c) 解释:可变意味着“可更改”。StringBuffer 对象可以在创建后进行修改。它们的内部字符数组可以扩展并直接修改,避免了每次更改都创建新对象的开销。 4) StringBuffer 的 __________ 是内部缓冲区可容纳的字符总数,在需要调整大小时可以增长,而无需创建新的对象实例。
答案:c) 解释:容量是指 StringBuffer 的内部缓冲区在需要自行调整大小时可以容纳的总字符数。长度是当前使用的字符数,而容量是分配的总空间。 5) 调用 StringBuffer 对象的 __________ 方法将从其当前内容创建一个新的 String 对象。
答案:c) 解释:StringBuffer 的 toString() 方法用于将可变的 StringBuffer 内容转换为不可变的 String 对象。调用此方法时,会在堆中实例化一个全新的 String 对象。 下一个主题Java 中的矩阵旋转 90 度 |
在本节中,我们将创建 Java 程序,将一个数字的各位相加,直到该数字变为个位数。该问题也称为数字根问题。示例假设 76345 是一个数字,我们需要找到它的各位数字之和,直到它变成...
阅读 3 分钟
在 Java 18 中,引入了 snippet 标签来解决 code 标签的缺点。Java 18 以新功能的形式在 Java 的 API 文档中添加了代码片段。JavaDoc 的标准 Doclet 在 Java 中包含 @snippet 标签,并且它...
阅读 3 分钟
java.lang.ref.Reference 类是 Java 中引用对象的抽象基类。它包含检索有关这些引用对象的信息的方法。但是,它不是直接子类,因为与引用对象的交互密切涉及垃圾收集器。声明:public abstract class Reference<T> extends Object ...
阅读 4 分钟
| Java ArrayList 大小 ArrayList 是 java.util 包的一部分,用于存储对象的动态列表。当添加或删除元素时,ArrayList 的大小可以动态地增加或减少。在 Java 中,要获取长度(元素数量)...
阅读 4 分钟
在本节中,我们将学习如何在 Java 中找到从左上角到右下角的可能路径。这是面试中一个突出的问题。从左上角到右下角的约束是:从……
5 分钟阅读
继承是 Java 中面向对象编程 (OOP) 四大组成部分中的基本原则。象征性地,继承允许子类通过这种关系获得所有父类的字段和方法。该功能使开发人员能够重用代码块并创建可维护和可扩展的程序,从而实现...
阅读 3 分钟
克隆是 Java 中的一个基本概念,它允许开发人员创建对象的副本。此过程对于各种场景至关重要,例如保存对象的状态、创建备份或实现某些设计模式。但是,Java 提供了两种不同的类型...
7 分钟阅读
在本教程中,我们将讨论如何在 Java 中计算最大和,使得没有两个元素是相邻的。输入是一个填充了正数的数组 (inptArr[])。示例 1:输入 int inptArr[] = {15, 15, 110, 1100, 110, 15, 7, 80} 输出 1210 解释:...
阅读 8 分钟
A 是一种特殊的反编译器,它以类文件作为输入并生成 Java 源代码作为输出。反编译是编译的精确逆过程。因此,反编译器不会生成源代码的副本。这是因为一个...
阅读 3 分钟
关联数组将元素存储为 (键, 值) 对。它是一个唯一键的集合,每个键都与一个特定的值相关联。它也称为映射,是一种抽象数据类型,其中每个键在集合中最多出现一次。在 Java 中,...
阅读 3 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India