java基础之你所不知道的字符串

字符串

String

String是一个final修饰的不可变类,其属性也是final的,底层使用char数组存储。

字符串拥有字符串常量池,对于String s = new String("xyz");

如果之前没有用过xyz的话,需要创建两个对象,一个是new String创建的对象,一个是常量xyz对象的内容创建的对象(常量池中一个,堆中一个)

public static void main(String[] args) {
    String s = new String("zxc");
}


  public static void main(java.lang.String[]);
    Code:
       0new           #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
      10return
}

如果之前就存在xyz的话,只需要创建一个对象new String对象

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
       3new           #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
      13return
}

Process finished with exit code 0

字符串拼接

字符串拼接的字节码,在java8中进行字符串拼接时会编译为StringBuilder。

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
       4return

  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
      10new           #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          21
      32: goto          4
      35return
}

intern方法

在使用字符串拼接之后生成的字符串如果调用intern()方法,就会返回该字符串所对应的常量池中字符串的地址值

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);// false
System.out.println(s3 == s5);// true
System.out.println(s3 == s6);// true
System.out.println(s4 == s5);// false
System.out.println(s4 == s6);// false
System.out.println(s5 == s6);// true

其在jdk6中,当调用intern方法时,如果字符串常量池先前已经创建出该字符串对象,则返回池中的该字符串的引用,否则,将此字符串对象添加到字符串常量池中,并返回该字符串对象的引用

在jdk6+中,当调用intern方法时,如果字符串常量池先前已经创建出该字符串对象,则返回池中的该字符串的引用,否则,如果该字符串对象已经存在于java堆中,则将堆中此对象的引用添加到字符串常量池中,并且返回该引用;如果堆中不存在,则在池中创建该字符串并返回其引用

format格式化
String.format("%.2f", bound * 0.5)

内部使用的是Formatter

StringBuilder和StringBuffer

与StringBuffer相比,StringBuilder是线程不安全的,在单线程上操作比StringBuffer性能损耗小。

默认初始值大小为16,如果进行扩容的话,会进行数据内容的赋值,增加性能损耗,如果确定数据大小,可以指定大小

https://zhhll.icu/2020/java基础/面向对象/12.java基础之字符串/

本文由 mdnice 多平台发布

posted @ 2023-10-22 11:39  拾光师  阅读(4)  评论(0编辑  收藏  举报  来源