先来一道面试题吧
/*以下Java代码会在运行时内存中开辟几块空间*/
String s = "a"+"b"+"c";
/*
事实是恒为一块,因为编译器在编译时会对其做优化
在反编译的字节码码文件中你看到的应该是这样
*/
String s = "abc";
/*有些问题多看看生成的字节码文件就解决了,因为最终执行的是class文件而不是java文件*/
好下面进入正题
这三种字符串存储字符用的都是char[],这一点没什么好说的
直接将char型数组传递到打印流里得到的是所有元素拼接到一起的具体内容而不是地址值
先看看StringBuffer吧,这个类中提供的追加,替换等方法都是同步方法,
所以他是一个线程安全的类
当需要追加一个内容时他不会像String那样在常量池中开启新的空间,那样对资源是一笔不小的开销,同时,效率也是很低的
StringBuilder和StringBuffer类似,在官方的文档注释中推荐在非并发场景下优先使用此类,因为他是效率最高的
做个测试吧,三方各做10万次追加操作
@Test
void test2(){
String s = "";
StringBuilder sbu = new StringBuilder();
StringBuffer sb = new StringBuffer();
byte[] bys = new byte[100000];
long begin1 = System.currentTimeMillis();
for1:for(byte b : bys){
s+=" ";
}
System.out.println("String:"+(System.currentTimeMillis() - begin1));
long begin2 = System.currentTimeMillis();
for2:for(byte b : bys){
sb.append(" ");
}
System.out.println("StringBuffer:"+(System.currentTimeMillis() - begin2));
long begin3 = System.currentTimeMillis();
for3:for(byte b : bys){
sbu.append(" ");
}
System.out.println("StringBuilder:"+(System.currentTimeMillis() - begin3));
}
控制台结果
好了,StringBuilder牛哔
另外再放两张图
这是跑SpringBuffer和StringBuilder时的内存使用
这是跑String时的内存使用
可以看到有一个明显的上升趋势
牛哔