参考于:https://www.cnblogs.com/dolphin0520/p/3778589.html
String
- 被final修饰
- 大部分方法也被final修饰,反例有
CaseInsensitiveComparator 尽量不要说这个点,会引入 比较器排序知识点,未掌握
- String对象的改变,不会影响原对象,而是创建新的对象,所以,String对象不建议经常变动,否则,会造成大量的运行时常量池内存浪费。
- 每次String str = "zhangsan"生成,都会去常量池中查找"zhangsan",如果有,将地址值修改为原来内容的地址值;没有,那就单独开辟内存空间。
new关键字来生成对象是在堆区进行的,堆区进行对象生成的过程是不会去检测该对象是否已经存在的,所以每次String str = new String("zhangsan"),都是不同的新对象。即:凡是new出来的,正如字面意思,都是新对象。
故
String str1 = "hello world";
String str2 = new String("hello world");
String str3 = "hello world";
String str4 = new String("hello world");
System.out.println(str1==str2);
false
System.out.println(str1==str3);
true
System.out.println(str2==str4); false
在分析下面代码
public class Main {
public static void main(String[] args) {
String string = "";
for(int i=0;i<10000;i++){
string += "hello";
}
}
}
为了更好的分析,我们先使用 javac Main.java
编译一下 Main.class 文件
接下来 就可以使用 javap Main.class 得到 注意观察 下面 变红的
Compiled from "Main.java"
public class Main {
public Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: sipush 10000
9: if_icmpge 38
12: new #3 // class java/lang/StringBuilder
15: dup
16: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
19: aload_1
20: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: ldc #6 // String hello
25: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore_1
32: iinc 2, 1
35: goto 5
38: return
}
看到 是不是很扯淡?我没有写出来StringBuild,更没有调用append() 方法,别担心,这是 JVM 为了优化 减少性能浪费的。即便如次,我们也能看出来的1w,即:即便JVM 优化,依旧创建了1w个StringBuilder。你想想哪里优化了?其实是使用append()方法。 append()方法,会在原来的基础上修改原来的字符,返还This,不会造成大量的新常量池浪费,减少了gc次数,提高效率,但是创建了那么多的StringBuilder对象,效率还是不够高。
String对比StringBuilder
Builder拥有更好的性能,每次+操作,实际是在原来进行添加修改,减少常量池的损耗,为什么这么说,详细,往下看源码
StringBuilder
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
StringBuffer
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
你看,不管是StringBuilder,还是StirngBuffer,在使用append的时候,如果参数类型是String,那么直接相加,如果不是String的引用类型,那么就会先转为String,在进行相加。
所以,在大量相加字符串面前,不管是StringBuilder还是StringBuffer,性能都比String要好。
StringBuilder与StringBuffer对比。
因为Buffer中加入了 synchronized 关键字,这个关键字是在多线程访问时起到安全保护作用的。
所以,StringBuffer是线程安全的。
总而言之 :
不考虑线程安全 大量“加”操作的时候,builder > buffer >String
在线程安全下,大量使用“加”操作,只能使用buffer。
如果看完,还要问Buffer为什么比String要性能好,因为他是有append()方法。
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤
评论(0)