new String創建了多少個String對象


new String創建了多少個String對象

 

public class NewString {
    public static void main(String[] args) {
        String str0 = new String("hello" + " world");
        String str1 = "hello" + " world";
        String str2 = "hello world";
        String str3 = new String("hello") + " wor" + "ld";
        String str4 = new String("hello") + new String(" world");
        String str5 = "he" + "llo" + new String(" world");
        String str6 = (new String("hello") + new String(" world")).intern();
        String str7 = "when " + "I " + "was "
                + new String("listen " + " to" + " the") + " radio,"
                + "waiting" + "for ...";
        System.out.println(str0 == str1);
        System.out.println(str1 == str2);
        System.out.println(str2 == str3);
        System.out.println(str2 == str4);
        System.out.println(str2 == str5);
        System.out.println(str2 == str6);
    }
}

 

運行結果:

false

true

false

false

false

true

 

解析:

可以通過javap解析NewString.class文件。

命令:javap -v c:\NewString.class >>c:\ssu.txt

得到對應常量池信息:

Constant pool:

   #1= Class              #2             // NewString

   #2= Utf8               NewString

   #3= Class              #4             // java/lang/Object

   #4= Utf8               java/lang/Object

   #5= Utf8               <init>

   #6= Utf8               ()V

   #7= Utf8               Code

   #8= Methodref          #3.#9          // java/lang/Object."<init>":()V

   #9= NameAndType        #5:#6          // "<init>":()V

  #10= Utf8               LineNumberTable

  #11= Utf8               LocalVariableTable

  #12= Utf8               this

  #13= Utf8               LNewString;

  #14= Utf8               main

  #15= Utf8              ([Ljava/lang/String;)V

  #16= Class              #17            // java/lang/String

  #17= Utf8               java/lang/String

  #18= String             #19            // hello world

  #19= Utf8               hello world

  #20= Methodref          #16.#21        // java/lang/String."<init>":(Ljava/lang/String;)V

  #21= NameAndType        #5:#22         // "<init>":(Ljava/lang/String;)V

  #22= Utf8               (Ljava/lang/String;)V

  #23= Class              #24            // java/lang/StringBuilder

  #24= Utf8              java/lang/StringBuilder

  #25= String             #26            // hello

  #26= Utf8               hello

  #27= Methodref          #16.#28        // java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;

  #28= NameAndType        #29:#30        // valueOf:(Ljava/lang/Object;)Ljava/lang/String;

  #29= Utf8               valueOf

  #30= Utf8              (Ljava/lang/Object;)Ljava/lang/String;

  #31= Methodref          #23.#21        // java/lang/StringBuilder."<init>":(Ljava/lang/String;)V

  #32= String             #33            //  wor

  #33= Utf8                wor

  #34= Methodref          #23.#35        // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

  #35= NameAndType        #36:#37        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

  #36= Utf8               append

  #37= Utf8              (Ljava/lang/String;)Ljava/lang/StringBuilder;

  #38= String             #39            // ld

  #39= Utf8               ld

  #40= Methodref          #23.#41        // java/lang/StringBuilder.toString:()Ljava/lang/String;

  #41= NameAndType        #42:#43        // toString:()Ljava/lang/String;

  #42= Utf8               toString

  #43= Utf8               ()Ljava/lang/String;

  #44= String             #45            //  world

  #45= Utf8                world

  #46= Methodref          #16.#47        // java/lang/String.intern:()Ljava/lang/String;

  #47= NameAndType        #48:#43        // intern:()Ljava/lang/String;

  #48= Utf8               intern

  #49= String             #50            // when I was

  #50= Utf8               when I was

  #51= String             #52            // listen  to the

  #52= Utf8               listen  to the

  #53= String             #54            //  radio,

  #54= Utf8                radio,

  #55= String             #56            // waiting

  #56= Utf8               waiting

  #57= String             #58            // for ...

  #58= Utf8               for ...

  #59= Fieldref           #60.#62        // java/lang/System.out:Ljava/io/PrintStream;

  #60= Class              #61            // java/lang/System

  #61= Utf8               java/lang/System

  #62= NameAndType        #63:#64        // out:Ljava/io/PrintStream;

  #63= Utf8               out

  #64= Utf8              Ljava/io/PrintStream;

  #65= Methodref          #66.#68        // java/io/PrintStream.println:(Z)V

  #66= Class              #67            // java/io/PrintStream

  #67= Utf8               java/io/PrintStream

  #68= NameAndType        #69:#70        // println:(Z)V

  #69= Utf8               println

  #70= Utf8               (Z)V

  #71= Utf8               args

  #72= Utf8               [Ljava/lang/String;

  #73= Utf8               str0

  #74= Utf8               Ljava/lang/String;

  #75= Utf8               str1

  #76= Utf8               str2

  #77= Utf8               str3

  #78= Utf8               str4

  #79= Utf8               str5

  #80= Utf8               str6

  #81= Utf8               str7

  #82= Utf8               StackMapTable

  #83= Class              #72            // "[Ljava/lang/String;"

  #84= Utf8               SourceFile

  #85= Utf8               NewString.java

 

 

 

String str0 = new String("hello"+ " world");

編譯器優化後等同於new String("hello world"),

對應常量池中 #19 = Utf8              hello world,

在常量池中找到或者創建“hello world”字符串對象,

在堆中創建“hello world”字符串對象,並將堆中引用返回給str0.

 

String str1 = "hello" + "world";

編譯器優化後等同於"hello world",

對應常量池中 #19 = Utf8              hello world,

在常量池中找到或者創建“hello world”,並且將常量池中引用返回給str1,

在堆中沒有創建對象。

       

String str2 ="hello world" ;

str2和str1一樣,返回的是常量池中"hello world"的引用。

 

String str3 = new String("hello")+ " wor" + "ld";

對應常量池中

  #26= Utf8               hello

  #33= Utf8                wor

  #39= Utf8               ld

在常量池中找到或者創建“hello”,“ wor”和“ld”,

在堆中創建“hello”、“hello world”,並且將堆中引用返回給str3.

字符串的拼接通過StringBuffer完成。

 

String str4 = new String("hello")+ new String(" world");

對應常量池中

  #26= Utf8               hello

  #45= Utf8                world

在常量池中找到或者創建“hello”,“ world”,

在堆中創建“hello”,“ world”、“hello world”,並且將堆中引用返回給str4.

 

String str5 = "he" +"llo" + new String(" world");

編譯優化後等同於"hello"+new String(" world");

對應常量池中

  #26= Utf8               hello

  #45= Utf8                world

在常量池中找到或者創建“hello”,“ world”,

在堆中創建“ world”、“hello world”,並且將堆中引用返回給str5.

 

String str6 = (newString("hello") + new String(" world")).intern();

對應常量池中

  #26= Utf8               hello

  #45= Utf8                world

在常量池中找到或者創建“hello”,“ world”,

在堆中創建“hello”、“ world”、“hello world”,

intern作用將在常量池中找到或者創建“helloworld”對象並且返回常量池中引用。

 

String str7 = "when " + "I" + "was " + new String("listen " + " to" +" the") + " radio," + "waiting" + "for...";

編譯器優化後等同於"when I was "+ new String("listen  to the") + " radio,"+"waiting" + "for ...";

對應常量池中

  #50= Utf8               when I was

  #52= Utf8               listen  to the

  #54= Utf8                radio,

  #56= Utf8               waiting

  #58= Utf8               for ...

在常量池中創建或者找到“when I was ”、“listen to the”、“ radio,”、“waiting”、“for ...”,

在堆中創建“listen to the”、“when I was listen to the radio,waiting for ...”。

 

總結:

  1. 賦值號“=”後面或者new String()裏面的連續字符串連接直接優化爲連接後的字符串。如"I"+" want"+new String(" tochange"+" the world")等同於"Iwant"+new String(" to change the world"),
  2. 在new String()後面的連續字符串連接不能被優化。
  3. 直接字符串則會在常量池中先查找是否有該對象,沒有則創建該對象,並且返回常量池中對應引用。
  4. 有new String()的字符串,則先會在常量池中查找或者創建,讓後在堆中創建對象並且返回堆中引用。
  5. 有new String()的字符串連接,則先會在常量池中查找或者創建,然後在堆中創建對象並且返回堆中引用。
  6. 有intern()的字符串,最後返回在常量池中查找或者創建的對象。
參考鏈接:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章