字符串
String
String是一个final修饰的不可变类,其属性也是final的,底层使用char数组存储。
字符串拥有字符串常量池,对于String s = new String(“xyz”);
如果之前没有用过xyz的话,需要创建两个对象,一个是new String创建的对象,一个是常量xyz对象的内容创建的对象(常量池中一个,堆中一个)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static void main(String[] args) { String s = new String("zxc"); }
public static void main(java.lang.String[]); Code: 0: new #2 // class java/lang/String 3: dup 4: ldc #3 // String zxc 6: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V 9: astore_1 10: return }
|
如果之前就存在xyz的话,只需要创建一个对象new String对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static void main(String[] args) { String ss = "zxc"; String s = new String("zxc"); }
public static void main(java.lang.String[]); Code: 0: ldc #2 // String zxc 2: astore_1 3: new #3 // class java/lang/String 6: dup 7: ldc #2 // String zxc 9: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V 12: astore_2 13: return }
Process finished with exit code 0
|
字符串拼接
字符串拼接的字节码,在java8中进行字符串拼接时会编译为StringBuilder。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class TestString { public static void main(String[] args) { String s = null; for(int i = 0;i<10;i++){ s = s + i; } } }
public class com.zhanghe.study.stream.TestString { public com.zhanghe.study.stream.TestString(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return
public static void main(java.lang.String[]); Code: 0: aconst_null 1: astore_1 2: iconst_0 3: istore_2 4: iload_2 5: bipush 10 7: if_icmpge 35 10: new #2 // class java/lang/StringBuilder 13: dup 14: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V 17: aload_1 18: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 21: iload_2 22: invokevirtual #5 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 25: invokevirtual #6 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 28: astore_1 29: iinc 2, 1 32: goto 4 35: return }
|
intern方法
在使用字符串拼接之后生成的字符串如果调用intern()方法,就会返回该字符串所对应的常量池中字符串的地址值
1 2 3 4 5 6 7 8 9 10 11 12
| String s1 = "aa"; String s2 = "bb"; String s3 = "aabb"; String s4 = s1+s2; String s5 = "aa"+"bb"; String s6 = s4.intern(); System.out.println(s3 == s4); System.out.println(s3 == s5); System.out.println(s3 == s6); System.out.println(s4 == s5); System.out.println(s4 == s6); System.out.println(s5 == s6);
|
其在jdk6中,当调用intern方法时,如果字符串常量池先前已经创建出该字符串对象,则返回池中的该字符串的引用,否则,将此字符串对象添加到字符串常量池中,并返回该字符串对象的引用
在jdk6+中,当调用intern方法时,如果字符串常量池先前已经创建出该字符串对象,则返回池中的该字符串的引用,否则,如果该字符串对象已经存在于java堆中,则将堆中此对象的引用添加到字符串常量池中,并且返回该引用;如果堆中不存在,则在池中创建该字符串并返回其引用
1
| String.format("%.2f", bound * 0.5)
|
内部使用的是Formatter
StringBuilder和StringBuffer
与StringBuffer相比,StringBuilder是线程不安全的,在单线程上操作比StringBuffer性能损耗小。
默认初始值大小为16,如果进行扩容的话,会进行数据内容的赋值,增加性能损耗,如果确定数据大小,可以指定大小