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对象