Java之String/StringBuffer/StringBuilder
目录
三者关系
https://blog.csdn.net/jisuanjiguoba/article/details/82531868
https://www.runoob.com/w3cnote/java-different-of-string-stringbuffer-stringbuilder.html
https://www.zhihu.com/question/20101840
- 快慢关系
StringBuilder>StringBuffer>String
为何String最慢呢?因为String是不可变的,所以要修改时(其实就是将String指向了一个新对象,内容是修改的字符串值),涉及到创建和回收对象,所以耗时。具体解释如下:
![]()
- 线程安全与否
String不可变,所以自然是线程安全
StringBuffer是线程安全,因为很多方法都由synchronized关键词来修饰
StringBuilder不是线程安全的
![]()
- 三者相互转换
- String vs. StringBuffer (StringBuilder转换类似)
public class StringAndStringBufferSwitch {
public static void main(String[] args) {
//String -> StringBuffer
//创建一个String对象
String str = "Hi Java!";
System.out.println(str);
//方式一:构造方法
StringBuffer buffer = new StringBuffer(str);
System.out.println(buffer);
//方式二:通过append方法
StringBuffer buffer2 = new StringBuffer();
buffer2.append(str);
System.out.println(buffer2);
//StringBuffer -> String
//创建一个StringBuffer对象
StringBuffer buffer3 = new StringBuffer();
buffer3.append("Happy birthday Java!");
System.out.println(buffer3);
//方式一:通过构造方法
String str2 = new String(buffer3);
System.out.println(str2);
//方式二:通过toString方法
String str3 = buffer3.toString();
System.out.println(str3);
}
}
String
https://github.com/CyC2018/CS-Notes
https://blog.csdn.net/fly_fly_fly_pig/article/details/82492491
- 特性
不可变,final修饰。在java8中,String内部使用char数组;在java9中,使用byte数组
不可变的好处:适合作map的键值、天生支持多线程、比较安全(比如传送网络地址时)、String pool的需要 - 关于String的="xxx"和new String("xxx")区别,以及字符串相等的判定,以及intern()函数的使用,见下面的代码解释:
public class TestString {
public static void main(String[] args) {
//直接使用="xxx"构造,会自动将“xxx”放入String pool,因此s2构造时,直接指向s1当时构造的“abc”。因此两者hashcode或==都一样
String s1 = "abc";
String s2 = "abc";
System.out.println(s1.equals(s2));
System.out.println("s1.hashcode: "+s1.hashCode()+"; s2.hashcode: "+s2.hashCode());
System.out.println(s1 == s2);
//此时String pool中已有“abc”,因此虽然是使用new String("abc")新建一个对象,但是查找到String pool已有,同样也是指向相同的引用
String s3 = new String("abc");
System.out.println("s3.hashcode: "+s3.hashCode());
//然而,若我们用new String新建两个相同的字符串但是之前未出现在String pool中,则两者的引用不同
String s4 = new String("xyz");
String s5 = new String("xyz");
System.out.println(s4.equals(s5)); //true,因为值相等
System.out.println("s4.hashcode: "+s4.hashCode()+"; s5.hashcode: "+s5.hashCode());
System.out.println(s4 == s5); //不同,因为是两个不同的对象,虽然指向的是同一个地址
//所以要注意,hashcode相同,也不一定就是同一个对象~
//使用intern()可手动将字符串放入String pool,这样的话==就为true
String s6 = s4.intern();
String s7 = s4.intern();
System.out.println(s6.equals(s7));
System.out.println("s6.hashcode: "+s6.hashCode()+"; s7.hashcode: "+s7.hashCode());
System.out.println(s6 == s7);
//若使用一个对象作为新new对象的构造函数的参数时,value和hash都相同,但是s7,s8还是不同的对象。。
String s8 = new String(s7);
System.out.println(s7.equals(s8));
System.out.println("s7.hashcode: "+s7.hashCode()+"; s8.hashcode: "+s8.hashCode());
System.out.println(s7 == s8);
}
}
result:
true
s1.hashcode: 96354; s2.hashcode: 96354
true
s3.hashcode: 96354
true
s4.hashcode: 119193; s5.hashcode: 119193
false
true
s6.hashcode: 119193; s7.hashcode: 119193
true
true
s7.hashcode: 119193; s8.hashcode: 119193
false
注意:在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。
- 关于new String("xxx")后的操作
会生成两个对象,一个是在String pool中生成指向“xxx”的字符串对象,一个是new之后在堆上生成的字符串对象 - String类方法
https://www.runoob.com/java/java-string.html
StringBuffer
https://www.runoob.com/java/java-stringbuffer.html
- 特殊方法:
public class TestStringBuffer {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("abc");
System.out.println(s1);
s1.append("def");
System.out.println(s1);
s1.reverse();
System.out.println(s1);
s1.delete(1,2); //删除下标为[1,2)的字符
System.out.println(s1);
s1.insert(1,1); //(int offset, int i),将int型的i插入到字符串offset位置,其他字符后移
System.out.println(s1);
s1.replace(1,4,"kkk"); //用“kkk”替换掉下标为[1,4)的字符
System.out.println(s1);
}
}
result:
abc
abcdef
fedcba
fdcba
f1dcba
fkkkba
- 与String同样的方法见https://www.runoob.com/java/java-stringbuffer.html
StringBuilder
StringBuffer 与 StringBuilder 中的方法和功能完全是等价的
https://www.cnblogs.com/onetheway2018/p/11553168.html


浙公网安备 33010602011771号