84669 人学习
152542 人学习
20005 人学习
5487 人学习
7821 人学习
359900 人学习
3350 人学习
180660 人学习
48569 人学习
18603 人学习
40936 人学习
1549 人学习
1183 人学习
32909 人学习
为什么说String的拼接会产生很多的无用对象呢?eg.String str = "";while(true){
str +="abc";
}
按我的理解,字符串拼接只会在常量池中创建共享对象,常量池的对象会被垃圾回收器回收吗?为什么说会产生很多无用的对象,需要垃圾回收,从而影响程序性能呢?
拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...
对于楼主所说的字符串拼接只会在常量池中创建共享对象这句话,我没有理解具体指的是什么,但是我可以解释下这种写法为什么会产生很多无用对象,希望对楼主有所帮助。
以下为答案:
先看上图,JDK中String类为final类,用来存放String字符的value也是final!
这就说明string对象在创建完成后value值就已经无法再修改了!故此每一次循环产生的字符串肯定都是新的String对象。但是上述这段代码中产生的对象比你想象中的还要多!please继续看图!
----------------------靓丽的分割线-----------------------------
第二张图红框内即为第一张红框内的反编译代码。从图中可以见得:a+=a;做了以下事情:
调用String.valueOf(a),这一步因为a也是字符串所以不会产生新的对象。
new StringBulid(第一部的对象其实就是字符串a),这一步会产生一个Stringbuild对象。
.append(被添加的字符串)
.toString(),这一步会调用Stringbuild的toString方法。
我们再看下Stringbuild的toString()源码
public String toString() { // Create a copy, don't share the array return new String(value, 0, count); }
哎呀!怎么又创建了一个String对象啊!
到这里a+=a的解析就完成了,所以每一次循环内的字符串相加操作,其实都至少创建了一个StringBuild对象和一个String对象啊!
String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
经常修改的变量 要用StringBuffer 奥~
...jdk1.8之后才字符串的多次拼接才会使用StringBuild 把。。老版本不是这样的把!~~我上次看了一片文章0 0,不知道有没有错。1.8以前需要String的多次修改需要使用StringBuffer或者StringBuilder。1.8启用了 语法糖修改了这一块,让我们不用显式调用StringBuilder 即可享用高效。
还有你对string只会在常量池中创建共享对象,
str +="abc"; 1.abc 2.abcabc 3........
难道这创建的每一个不都是无用的对象么?除了最后的结果,GC的回收也是需要时间的把。
因为string则是因为final修饰char[ ]的原因,每次都要创建新的对象,而StringBuilder这类是这所以的高效的原因是数组动态扩容把,一般是添加操作把,只有容量满了才创建新的更大的char[],将旧数据拷贝之后再添加,综上stringbuilder减少了对象的生成把,不用每次都要生成新的对象。敬请大牛拍砖指导!~!~!~
对于楼主所说的字符串拼接只会在常量池中创建共享对象这句话,我没有理解具体指的是什么,但是我可以解释下这种写法为什么会产生很多无用对象,希望对楼主有所帮助。
以下为答案:
先看上图,JDK中String类为final类,用来存放String字符的value也是final!
这就说明string对象在创建完成后value值就已经无法再修改了!故此每一次循环产生的字符串肯定都是新的String对象。但是上述这段代码中产生的对象比你想象中的还要多!please继续看图!
----------------------靓丽的分割线-----------------------------
第二张图红框内即为第一张红框内的反编译代码。从图中可以见得:
a+=a;做了以下事情:
调用String.valueOf(a),这一步因为a也是字符串所以不会产生新的对象。
new StringBulid(第一部的对象其实就是字符串a),这一步会产生一个Stringbuild对象。
.append(被添加的字符串)
.toString(),这一步会调用Stringbuild的toString方法。
我们再看下Stringbuild的toString()源码
哎呀!怎么又创建了一个String对象啊!
到这里a+=a的解析就完成了,所以每一次循环内的字符串相加操作,其实都至少创建了一个StringBuild对象和一个String对象啊!
String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
经常修改的变量 要用StringBuffer 奥~
...jdk1.8之后才字符串的多次拼接才会使用StringBuild 把。。老版本不是这样的把!~~
我上次看了一片文章0 0,不知道有没有错。
1.8以前需要String的多次修改需要使用StringBuffer或者StringBuilder。
1.8启用了 语法糖修改了这一块,让我们不用显式调用StringBuilder 即可享用高效。
还有你对string只会在常量池中创建共享对象,
难道这创建的每一个不都是无用的对象么?除了最后的结果,GC的回收也是需要时间的把。
因为string则是因为final修饰char[ ]的原因,每次都要创建新的对象,
而StringBuilder这类是这所以的高效的原因是数组动态扩容把,一般是添加操作把,只有容量满了才创建新的更大的char[],将旧数据拷贝之后再添加,综上stringbuilder减少了对象的生成把,不用每次都要生成新的对象。敬请大牛拍砖指导!~!~!~