Java字符串追加时的自动优化机制 - StringBuilder类

1. String 类(字符串)的特点

  • 字符串是常量,创建后不可改变;
  • 字符串字面值存储在字符串池中,可以共享;

JVM内存管理中:栈、堆、方法区(方法区中有常量池,常量池中嵌套了字符串池)

先来看个简单的案例:

public class TestString {
    public static void main(String[] args) {
        String str = "Hello";
        
        for (int i = 0; i < 100; i++) {
            str += i;
        }
        
        System.out.println(str);
    }
}

这种追加字符串的情况,在理论会产生若干的中间变量,浪费内存
而实际结果却不然,如何说明和证明呢?

2. Java反编译分析字符串追加时的优化

找到编译生成的.class文件,然后对应目录下,执行反编译命令:
javap -v TestString > TestString.bytecode
命令说明:
-v 是输出附加信息
TestString 是类名即文件名
> 重定向符号,将命令的输出全部重定向到文件中保存
.bytecode 后缀名无所谓,使用.txt也一样,我们只需要查看内容

Java反编译

查看和分析反编译信息:
反编译内容分析

进而得出结论:
str += i; // 被JVM自动优化了,实际不会产生中间变量
JDK的实现方式是什么?

  1. 自动创建了StringBuilder对象
  2. 调用StringBuilder的构造方法
  3. 调用StringBuilder的append(int i)方法
  4. 调用StringBuilder的toString()方法转回为String类型,并赋值给str
    StringBuilder直接在str指向的对象空间里扩展空间追加。

3. StringBuilder类介绍

参考JDK1.8 API 文档。

public final class StringBuilder
    extends Object
    implements Serializable, CharSequence

一个可变的字符序列。此类提供与StringBuffer的API,但不保证同步。 此类设计用作简易替换为StringBuffer在正在使用由单个线程字符串缓冲区的地方(如通常是这种情况)。 在可能的情况下,建议使用这个类别优先于StringBuffer ,因为它在大多数实现中将更快。
StringBuilder的主要appendinsert方法,它们是重载的,以便接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符附加或插入字符串构建器。 append方法始终在构建器的末尾添加这些字符; insert方法将insert添加到指定点。

一般情况下,如果某人是指的一个实例StringBuilder ,则sb.append(x)等同于sb.insert(sb.length(), x) 。
每个字符串构建器都有一个容量。 只要字符串构建器中包含的字符序列的长度不超过容量,则不需要分配新的内部缓冲区。 如果内部缓冲区溢出,则会自动变大。

StringBuilder不能安全使用多线程,因为异步问题无法保证数据安全访问。如果需要同步,那么建议使用StringBuffer。

除非另有说明,否则将null参数传递给null中的构造函数或方法将导致抛出NullPointerException 。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容