java字符串拼接在编译时优化测试

阅读更多

为了验证编译器对于String相关代码的字节码优化,我简单的做了个测试:

jdk版本:1.7.0_51

 java 用例代码:

package com.rsp.shiro;

/**
 * Created by cd_huang on 2017/4/1.
 */
public class StringTest {
	public static String StaticString(){
		return "BBB";
	}
	public static String getString1(){
		return "AAA"+"BBB";
	}
	public static String getString2(){
		return new StringBuilder().append("AAA").append("BBB").toString();
	}
	public static String getString3(){
		return "AAA"+StaticString();
	}
	public static String getString4(){
		return new StringBuilder().append("AAA").append(StaticString()).toString();
	}
}

 命令行输入:C:\Users\hcd>javac c:\StringTest.java
生成StringTest.class文件。

命令行输入:C:\Users\hcd>javap -v c:\StringTest.class
生成java编译后的字节码指令。

Classfile /c:/StringTest.class
  Last modified 2017-4-1; size 721 bytes
  MD5 checksum 60b413955d7484157009f74a40848d59
  Compiled from "StringTest.java"
public class com.rsp.shiro.StringTest
  SourceFile: "StringTest.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #11.#24        //  java/lang/Object."":()V
   #2 = String             #25            //  BBB
   #3 = String             #26            //  AAABBB
   #4 = Class              #27            //  java/lang/StringBuilder
   #5 = Methodref          #4.#24         //  java/lang/StringBuilder."":(
)V
   #6 = String             #28            //  AAA
   #7 = Methodref          #4.#29         //  java/lang/StringBuilder.append:(Lj
ava/lang/String;)Ljava/lang/StringBuilder;
   #8 = Methodref          #4.#30         //  java/lang/StringBuilder.toString:(
)Ljava/lang/String;
   #9 = Methodref          #10.#31        //  com/rsp/shiro/StringTest.StaticStr
ing:()Ljava/lang/String;
  #10 = Class              #32            //  com/rsp/shiro/StringTest
  #11 = Class              #33            //  java/lang/Object
  #12 = Utf8               
  #13 = Utf8               ()V
  #14 = Utf8               Code
  #15 = Utf8               LineNumberTable
  #16 = Utf8               StaticString
  #17 = Utf8               ()Ljava/lang/String;
  #18 = Utf8               getString1
  #19 = Utf8               getString2
  #20 = Utf8               getString3
  #21 = Utf8               getString4
  #22 = Utf8               SourceFile
  #23 = Utf8               StringTest.java
  #24 = NameAndType        #12:#13        //  "":()V
  #25 = Utf8               BBB
  #26 = Utf8               AAABBB
  #27 = Utf8               java/lang/StringBuilder
  #28 = Utf8               AAA
  #29 = NameAndType        #34:#35        //  append:(Ljava/lang/String;)Ljava/l
ang/StringBuilder;
  #30 = NameAndType        #36:#17        //  toString:()Ljava/lang/String;
  #31 = NameAndType        #16:#17        //  StaticString:()Ljava/lang/String;
  #32 = Utf8               com/rsp/shiro/StringTest
  #33 = Utf8               java/lang/Object
  #34 = Utf8               append
  #35 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #36 = Utf8               toString
{
  public com.rsp.shiro.StringTest();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."
":()V
         4: return
      LineNumberTable:
        line 6: 0

  public static java.lang.String StaticString();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #2                  // String BBB
         2: areturn
      LineNumberTable:
        line 8: 0

  public static java.lang.String getString1();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #3                  // String AAABBB
         2: areturn
      LineNumberTable:
        line 11: 0

  public static java.lang.String getString2();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: new           #4                  // class java/lang/StringBuilder
         3: dup
         4: invokespecial #5                  // Method java/lang/StringBuilder.
"":()V
         7: ldc           #6                  // String AAA
         9: invokevirtual #7                  // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        12: ldc           #2                  // String BBB
        14: invokevirtual #7                  // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        17: invokevirtual #8                  // Method java/lang/StringBuilder.
toString:()Ljava/lang/String;
        20: areturn
      LineNumberTable:
        line 14: 0

  public static java.lang.String getString3();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: new           #4                  // class java/lang/StringBuilder
         3: dup
         4: invokespecial #5                  // Method java/lang/StringBuilder.
"":()V
         7: ldc           #6                  // String AAA
         9: invokevirtual #7                  // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        12: invokestatic  #9                  // Method StaticString:()Ljava/lan
g/String;
        15: invokevirtual #7                  // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        18: invokevirtual #8                  // Method java/lang/StringBuilder.
toString:()Ljava/lang/String;
        21: areturn
      LineNumberTable:
        line 17: 0

  public static java.lang.String getString4();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: new           #4                  // class java/lang/StringBuilder
         3: dup
         4: invokespecial #5                  // Method java/lang/StringBuilder.
"":()V
         7: ldc           #6                  // String AAA
         9: invokevirtual #7                  // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        12: invokestatic  #9                  // Method StaticString:()Ljava/lan
g/String;
        15: invokevirtual #7                  // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        18: invokevirtual #8                  // Method java/lang/StringBuilder.
toString:()Ljava/lang/String;
        21: areturn
      LineNumberTable:
        line 20: 0
}

C:\Users\hcd>

 
可以看出来getString3() 方法和getString4()方法的字节码指令一摸一样,也就是编译器帮我们做了优化。
由于String对象时不可变对象,因此在对字符串进行拼接时,String对象总是会生成新的对象,所以其性能相对较差。
StringBuilder:一个非线程安全的字符串缓冲类,jdk1.5后出现。
所以,编译器在字符串对象拼接时,自动帮我们用StringBuilder实现了字符串拼接。



 

 

你可能感兴趣的:(java,String,字符串拼接,编译期优化,java字节码指令)