先上一段代碼
public class SimpleTest {
String str ="good";
char[] ch = {'a','b','c'};
public void change(String str,char ch[]){
str = "test ok";
ch[0] = 'g';
}
public static void main(String[] args) {
SimpleTest st = new SimpleTest();
st.change(st.str, st.ch);
System.out.print(st.str + " and ");
System.out.print(st.ch);
}
}
PS: 字符串一旦創(chuàng)建靶瘸,便不可修改
PPS: JVM內存可分為三個區(qū),堆(Heap)毛肋,棧(Stack)怨咪,方法區(qū)(Method)
堆區(qū):
1.存儲的全部是對象,每個對象都包含一個與之對應的class的信息润匙。(class的目的是得到操作指令)
2.jvm只有一個堆區(qū)(heap)被所有線程共享诗眨,堆中不存放基本類型和對象引用,只存放對象本身
棧區(qū):
1.每個線程包含一個棧區(qū)孕讳,棧中只保存基礎數據類型的對象和自定義對象的引用(不是對象)匠楚,對象都存放在堆區(qū)中
2.每個棧中的數據(原始類型和對象引用)都是私有的,其他棧不能訪問厂财。
3.棧分為3個部分:基本類型變量區(qū)芋簿、執(zhí)行環(huán)境上下文、操作指令區(qū)(存放操作指令)璃饱。
方法區(qū):
1.又叫靜態(tài)區(qū)与斤,跟堆一樣,被所有的線程共享帜平。方法區(qū)包含所有的class和static變量幽告。
2.方法區(qū)中包含的都是在整個程序中永遠唯一的元素,如class裆甩,static變量冗锁。
這段代碼都做了些什么
1.啟動一個JVM進程,首先從classpath找到SimpleTest.class文件嗤栓,讀取文件中的二進制數據冻河,然后把SimpleTest類的類信息存放在運行時數據區(qū)的方法區(qū)中箍邮,這一過程稱為SimpleTest的類加載過程
2.JVM定位到方法區(qū)中SimpleTest類的main()方法的字節(jié)碼,開始執(zhí)行它的指令叨叙。第一條語句是:
SimpleTest st = new SimpleTest();
語句很簡單啦锭弊,就是讓JVM創(chuàng)建一個SimpleTest實例,并且擂错,使引用變量st來引用這個實例味滞。看起來是小事一樁钮呀,具體JVM是怎么執(zhí)行的呢剑鞍?
1> 不就是建立一個SimpleTest實力嗎?JVM直奔方法區(qū)爽醋,先找到SimpleTest類的類信息再說蚁署。結果呢//木有@_@,這會兒的方法區(qū)內還沒有SimpleTest類蚂四」飧辏可JVM也不蠢...“自己動手,豐衣足食”遂赠,立馬加載了SimpleTest類久妆,并把類信息存放在方法區(qū)里。
2>類信息有了解愤,JVM第一件事就是在堆內為一個新的SimpleTest實例分配內存镇饺,這個SimpleTest實例持有著指向方法區(qū)中的內存地址,這個地址送讲,就存放在了SimpleTest實力的數據區(qū)奸笤。
3>在JVM進程中,每個進程都會擁有一個方法調用棧哼鬓,用來跟蹤線程運行中一系列的方法調用過程监右,棧中的每一個元素就被稱為棧幀,每當線程調用一個方法的時候就會向方法棧壓入一個新幀异希,用來存儲方法的參數健盒,局部變量和運算過程中的臨時數據。位于“=”前的st是一個在main()方法中定義的變量称簿,可見他是一個局部變量扣癣,因此它會被添加到執(zhí)行了main()方法的主線程的JAVA方法調用棧中。而“=”將把這個st變量指向堆區(qū)中的SimpleTest實例憨降,也就是說父虑,它持有指向SimpleTest實例的引用。
到這里授药,第一條語句就執(zhí)行完了士嚎。
3.接著就是調用st引用的對象的change方法呜魄,并把st所引用的字符串str和字符數組ch傳入change方法,以一個新幀被壓入change()方法所在的主線程的棧區(qū)莱衩。
4.在change()方法所在的棧區(qū)爵嗅,st.str被要求引用"test ok"所在內存的地址,注意到上面提及的笨蚁,“字符串一旦創(chuàng)建睹晒,便不可修改”,便是在main()方法所在的棧區(qū)內括细,st.str始終是引用了"good"所在的地址册招,在change()方法所在的棧區(qū)內,想改變st.str的引用為"test ok"勒极,實際上是重新開辟了另一塊內存存放"test ok",并將此時的st.str暫時指向"test ok"虑鼎,我們可以在兩處str和ch分別輸出他們的hashcode辱匿。
引用變量時,除了8個基本類型外(byte,short,int,long,float,double,char,boolean)炫彩,都是傳遞的內存地址匾七,包括數組。所以這里的char數組ch[]江兢,是st.ch所開辟出來的內存地址昨忆,被要求ch[0]重新指向字符'g'。
到此杉允,change()方法結束邑贴。
5.回到main()方法,st.str仍然指向"good"叔磷,但ch[0]指向了'g'拢驾。
輸出 good and gbc
Java沒有按引用傳遞,全部是按值傳遞改基,傳的是內存地址