標籤:style blog http color java 資料 2014 ar
string是位元殊的類,說參考型別,但不存在堆裡面,而且String str=new String("HelloWorld")這樣的重裝也說沒有的。
我們先來看一個方法
class Program { static void Main(string[] args) { String s = "HelloWorld"; Console.WriteLine(s); } }
然後我們用ildasm.exe工具把它產生IL語言來看一看它裡面是怎麼玩的:
.method private hidebysig static void Main(string[] args) cil managed{ .entrypoint // Code size 15 (0xf) .maxstack 1 .locals init ([0] string s) IL_0000: nop IL_0001: ldstr "HelloWorld" IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: call void [mscorlib]System.Console::WriteLine(string) IL_000d: nop IL_000e: ret} // end of method Program::Main
我們在裡面並沒有看見newObj(所以我們認為不在堆裡面)的指令,只有一個特殊ldstr(load string)指令,它用從中繼資料擷取一個文本常量字串(字串常量池)構造一個String對象。這證明了CLR說用一種特殊的方式構造了字串。
我們來做一個簡單例子看看:
class Program { static void Main(string[] args) { String s = "HelloWorld"; s = "HelloC#"; s = "HelloJava"; String s1= "HelloC#"; Console.WriteLine(s); } }
我們看看記憶體配置圖是怎麼走的:
首先CLR內部機制會在運行這個方法之前就會有"prologue"代碼去開闢記憶體空間,s和s1就說這個時候建立的。
我們建立了一個s的字串對象,賦值為HelloWorld,把s插入棧,然後內部機制去字串常量池中找HelloWorld副本,發現沒有找到就會建立一個,接著會去儲存這個HelloWorld在字串常量池中的地址(Line1)。然後我們為s對象在賦值為HelloC#,由於同一個對象,棧中不做操作,去字串常量池中找,沒找到則建立,然後修改s所儲存的地址(line 2),HelloJava同樣的操作。 再建立一個s1的string對象,把s1壓入棧,為S1賦值HelloC#,這個時候會去字元常量池中找,找到了就存這個引用。