欢迎大家来到IT世界,在知识的湖畔探索吧!
String
我们来看一下String的定义
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
}
欢迎大家来到IT世界,在知识的湖畔探索吧!
我们可以看到,String 是使用final修饰的,说明这个类不可以被继承,同时,value也是用final修饰的,说明value也重新指向新的应用,因此,String类是不可变的,但是对于这样一个问题,我们经常会感到困惑,我们来看一下这个代码
欢迎大家来到IT世界,在知识的湖畔探索吧!public class Test {
public static void main(String[] args){
String name = "Tom";
name = "Jack";
}
}
很多人会有一个疑问,不是说String是一个不可变的类么,那么为什么name的值改变了,这么理解是错误的,实际上,在内存中有一个Tom的字符串,然后,name只是指向了这个字符串,然后通過name = “Jack”;只是name指向了一个新的字符串,而在内存中,还是有一个Tom的字符串,这个是没有变化的,因此字符串是没有发生变化的。
StringBuilder
StringBuilder是一个可变的字符串,我们经常会使用StringBuilder来做字符串的拼接工作。在很多地方,我们都能看到这样一种说法,在for循环中,推荐我们使用StringBuilder来拼接字符串,而不是使用+,我们来看一下这段代码,看看究竟是什么原因?
public class StringBuilderTest {
public static void main(String[] args) {
List<String> list = Lists.newArrayList("str1", "str2", "str3", "str4");
String value = "";
for (String str : list) {
value = value + str;
}
System.out.println(value);
}
}
我们来使用javap -v来看一下+底层的实现原理
欢迎大家来到IT世界,在知识的湖畔探索吧!public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=5, args_size=1
0: iconst_4
1: anewarray #2 // class java/lang/String
4: dup
5: iconst_0
6: ldc #3 // String str1
8: aastore
9: dup
10: iconst_1
11: ldc #4 // String str2
13: aastore
14: dup
15: iconst_2
16: ldc #5 // String str3
18: aastore
19: dup
20: iconst_3
21: ldc #6 // String str4
23: aastore
24: invokestatic #7 // Method com/google/common/collect/Lists.newArrayList:([Ljava/lang/Object;)Ljava/util/ArrayList;
27: astore_1
28: ldc #8 // String
30: astore_2
31: aload_1
32: invokeinterface #9, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
37: astore_3
38: aload_3
39: invokeinterface #10, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
44: ifeq 81
47: aload_3
48: invokeinterface #11, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
53: checkcast #2 // class java/lang/String
56: astore 4
58: new #12 // class java/lang/StringBuilder
61: dup
62: invokespecial #13 // Method java/lang/StringBuilder."<init>":()V
65: aload_2
66: invokevirtual #14 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
69: aload 4
71: invokevirtual #14 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
74: invokevirtual #15 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
77: astore_2
78: goto 38
81: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
84: aload_2
85: invokevirtual #17 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
88: return
我们来看一下58行到74行,这一段代码就是用来实现+号的,它底层采用就是StringBuilder相当于这段代码
public class StringBuilderTest {
public static void main(String[] args) {
List<String> list = Lists.newArrayList("str1", "str2", "str3", "str4");
String value = "";
for (String str : list) {
value = new StringBuilder().append(value).append(str).toString();
}
System.out.println(value);
}
}
通过这段代码,我们只带,+每次都会创建一个StringBuilder对象,英雌,如果我们显示通过StringBuilder显示拼接字符串,这样会减少很多对象的创建,因此可以提升程序的性能,最终,可能改造成这段代码
public class StringBuilderTest {
public static void main(String[] args) {
List<String> list = Lists.newArrayList("str1", "str2", "str3", "str4");
StringBuilder sb = new StringBuilder();
for (String str : list) {
sb.append(str);
}
System.out.println(sb.toString());
}
}
StringBuffer
StringBuffer也是一个可变的字符串拼接类,通过它同样可以拼接字符串,那么它和StringBuilder究竟有什么区别呢,我们来看一下源码
StringBuffer的方法都加了synchronized锁,因此StringBuffer是一个线程安全的类,因此,我们在多线程的环境了,使用StringBuffer,在单线程的环境下StringBuilder,这样才是最优的使用原则
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/49685.html