84669 Lernen von Personen
152542 Lernen von Personen
20005 Lernen von Personen
5487 Lernen von Personen
7821 Lernen von Personen
359900 Lernen von Personen
3350 Lernen von Personen
180660 Lernen von Personen
48569 Lernen von Personen
18603 Lernen von Personen
40936 Lernen von Personen
1549 Lernen von Personen
1183 Lernen von Personen
32909 Lernen von Personen
为什么说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减少了对象的生成把,不用每次都要生成新的对象。敬请大牛拍砖指导!~!~!~