需要上課的人員:
題目一:
請問最後印出的set.size()與xx是多少?
答案:size=2,xx=10(反白中)
題目二:
請問最後印出的字串s為何?
答案:main method(反白中)
需要上課的人員:只要其中一題沒有答對,即需要上課。
八大型別與JVM記憶體位置
在JAVA中有八種比較特殊的型別,分別是:
-
boolean
-
btye
-
short
-
char
-
int
-
float
-
long
-
double
這八個型別比較特殊的原因,在於JVM中所存在的記憶體位置。在JVM中所存在的記憶體分配如下圖:
-
String pool:所有的字串存放的地方
-
Stack pool:所有Method執行的地方
-
Heap:所有物件存放的地方
由上方的描述可以知道,所有的物件都會被放到Heap區之中,而method如果要用到物件的話,會儲存Heap的記憶體位置,Heap中再儲存物件中的所有資料,而不是Stack pool裡儲存物件的所有資料;八大型別比較奇特的部份在於,它儲存的地方不會在Heap裡,而是在Stack pool中。那這樣又會有什麼影響呢?那就是傳值(Call by value)與傳址(Call by reference);也就是說,所有的八大型別在傳遞時,因為資料不是儲在Heap區,所以在傳遞給其他method時,接受的method必須自己持有一份(傳值),而八大型別之外的,全部都是傳遞記憶體位址;換句話說,八大型別在傳遞時是傳值,而八大型別之前的是傳址。
不過除了Stack pool與Heap之外,另外還有一個String pool,這個部份是String專用的,也因為有這個pool的存在,所以String這個型別在JAVA中是比較特殊的。
String型別與JVM記憶體位置
假設我們有程式碼如下:
我們來實際模擬一下JVM上的記憶體是如何處理的:
首先是Stack pool有一個main,裡面包含一個String s儲存了記憶體位址,如下圖:
再來是執行了changeWork時,並帶入參數s(傳址)。
最後是在變更s="changeWork method",所以應該是長成如下圖:
所以最後程式執行的結果應該是:
before changeWork s=main method
in changeWork s=changeWork method
after changeWork s=changeWork method
如果你的觀念是這樣子的,那我要先恭禧你,觀念是對的,只不過結過是錯的,下圖是程式實際運行上的結果:
我們可以看到最後一行是有問題的,原因其實是因為String是一個特殊的型別,如果今天我們修改的不是String的話,那就沒有這個問題了。
我們先回頭來重新確認一下程式:
下面我們重新來繪製正確的JVM記憶體位置圖:
首先是Stack pool裡面有一個main的method,並宣告了一個String s,此時因為s有值,所以在 String pool中會有一組文字main method,而Heap則是記憶了這個String pool的記憶體位置,如下圖:
再來是執行changeWork時,一樣將利用傳址的方式傳入:
最後在changeWork時變更文字的記憶體位置會變成如下圖:
在changeWork中因為程式 s="changeWork method",所以會在String pool裡生成一個新的記憶體位置,而這個新的記憶體位置並不會被記在舊的Heap裡的 #111裡,而是被記憶在新的記憶體位置,所以結果如上圖,而程式的執行結果:
這樣我們就可以很清楚的瞭解了為什麼會如此;JVM會有如此的行為,完全是因為String是一個特殊的物件所造成的,如果今天是一個單純的物件的話,就不會這麼麻煩了。
留言列表