Bootstrap

浅谈String对象内存常量池和StringBuilder的性能优化问题

String对象

特征

字符串常量在创建后值不可改变的

String s1 = "abc";

s1 = "def";

这不是改变,"abc"相当于创建了一个对象,而"def"有相当于创建了一个对象,改变的不是字符串常量,而是s1的引用地址

创建字符串有两种方式:

1.双引号创建,就会在字符串常量池中检查,如果存在,则不创建,若不存在,则在字符串常量池中创建

他的特点是无论在 程序中出现多少次,只要相同(字符顺序及大小写)就只会创建一次

2.构造方法创建,他会在堆内存中开辟空间

见下图详细比较:

代码

        String s1 = "abc";
        String s2 = "abc";
        System.out.println(s1==s2);
        String s3 = "a"+"b"+"c";
        System.out.println(s1 == s3);
        String s4 = new String("abc");
        System.out.println(s1 == s4);
        String s5 = new String("ab");
        String s6 = s5+"c";
        System.out.println(s6 == s5);
        System.out.println(s6 == s1);

前三行运行结果是true,"abc"为字符串常量,只会在常量池中创建一次,同一地址多以返回的回事true

四五行会检查常量池有没有 a b c这三个字符串,没有的话先创建,又因为都是常量,会采用常量优化机制,在编译的时候拼接成”abc“,并检查常量池是否有,若无创建,有这直接引用,所以返回的是true

六七行当采用构造方法的形式创建字符串时会在堆内存中开辟空间,创建String对象,同时会检测构造方法中”abc“在常量池中是否存在,若有则不创建,若无,创建。此时s4引用的是堆内存的地址,不相同,放回false

八九十行当采用+号拼接变量和常量字符串时,Java会自动在堆内存中创建stringbuilder对象,采用append的方法进行拼接,并采用toString方法在堆内存中创建一个新的String对象放回给s6,所以地址不同都会返回false

下图为内存图

String和StringBuilder性能优化

当我们书写代码是,遇到字符串的连加时通才都要采用Stringbuilder对象的append方法

当采用直接拼接时,内部会在堆内存中出创建StringBuilder对象和String对象,而且几个加号拼接,就会创建几个。

而用Stringbuilder对象进行拼接,无论多少次,都会只创建一次StringBuilder对象

 

;