【Java笔记】String类小结

【Java笔记】String类小结

运行版本为JAVA 8

问题:

  • String对"+"的重载发生了什么?
  • String s = new ("hello");创建了几个对象?
  • String、StringBuilder、StringBuffer类的区别?

String对"+"的重载发生了什么?

总结

  1. String s = "hello" + "world"; 因为两个都是编译器常量,编译器会进行常量折叠,变成String s = "helloworld";
  2. String hello = "hello"; String s = hello + "world"; 编译器调用StringBuilder的append()方法替代,最后调用toString()生成结果。

第一种情况:String s = "hello" + "world";

public class StringTest {

	public static void main(String[] args) {
		String s = "hello" + "world";
		System.out.println(s);
	}
  
}

对上面的类进行反编译(javap -c StringTest),截取一部分,如下所示

public static void main(java.lang.String[]);
  Code:
     0: ldc           #2                  // String helloworld
     2: astore_1
     3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
     6: aload_1
     7: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    10: return

从第0行可以得知编译器已经将helloworld两个字符串变成了helloworld

第二种情况:String s = 变量 + "world"

public class StringTest {

	public static void main(String[] args) {
    String hello = "hello";
		String s = hello + "world";
		System.out.println(s);
	}
  
}

同样进行反编译

public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String hello
       2: astore_1
       3: new           #3                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      10: aload_1
      11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      14: ldc           #6                  // String world
      16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: astore_2
      23: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      26: aload_2
      27: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      30: return
}

编译器创建了一个StringBuilder对象,每个字符串调用一次append()方法,总共2次。最后调用toString()生成结果(其实底层就是new String()),存到s中。

String s = new ("hello") 创建了几个对象?

总结

  • 如果常量池中没有"hello",创建两个对象,分别为常量池中的"hello"和堆中的对象
  • 如果常量池中有"hello",创建堆中的对象

代码一

public class StringTest {

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

反编译,# + 数字,表示对应的常量池中的项

Constant pool:
   #1 = Methodref          #6.#15         // java/lang/Object."<init>":()V
   #2 = Class              #16            // java/lang/String
   #3 = String             #17            // hello
   #4 = Methodref          #2.#18         // java/lang/String."<init>":(Ljava/lang/String;)V
   #5 = Class              #19            // StringTest
   #6 = Class              #20            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               SourceFile
  #14 = Utf8               StringTest.java
  #15 = NameAndType        #7:#8          // "<init>":()V
  #16 = Utf8               java/lang/String
  #17 = Utf8               hello
  #18 = NameAndType        #7:#21         // "<init>":(Ljava/lang/String;)V
  #19 = Utf8               StringTest
  #20 = Utf8               java/lang/Object
  #21 = Utf8               (Ljava/lang/String;)V

public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/String
       3: dup
       4: ldc           #3                  // String hello
       6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
       9: astore_1
      10: return

从第0行到第6行指令生成了一个String对象,第4行加载常量池中的"hello"到栈中。总共创建了两个对象。

代码二

public class StringTest {

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

反编译

Constant pool:
   #1 = Methodref          #6.#15         // java/lang/Object."<init>":()V
   #2 = String             #16            // hello
   #3 = Class              #17            // java/lang/String
   #4 = Methodref          #3.#18         // java/lang/String."<init>":(Ljava/lang/String;)V
   #5 = Class              #19            // StringTest
   #6 = Class              #20            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               SourceFile
  #14 = Utf8               StringTest.java
  #15 = NameAndType        #7:#8          // "<init>":()V
  #16 = Utf8               hello
  #17 = Utf8               java/lang/String
  #18 = NameAndType        #7:#21         // "<init>":(Ljava/lang/String;)V
  #19 = Utf8               StringTest
  #20 = Utf8               java/lang/Object
  #21 = Utf8               (Ljava/lang/String;)V

public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String hello
       2: astore_1
       3: new           #3                  // class java/lang/String
       6: dup
       7: ldc           #2                  // String hello
       9: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      12: astore_2
      13: return

第3行到第9行指令,生成了一个String对象,第7行中加载的"hello"与第0行中加载的"hello"指向的是同一个常量(#2),从String s = new ("hello")来看,只创建了一个对象。

String、StringBuilder、StringBuffer类的区别?

  • String不可变,保存字符的数组用final修饰;StringBuilder和StringBuffer可变,保存字符的数组没有用final修饰

  • StringBuilder线程不安全,性能较StringBuffer高;StringBuffer线程安全(方法都是同步的)

  • 三者都是final类,不可被继承;StringBuilder和StringBuffer继承自AbstractStringBuilder

# String 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×