結論:
個人認爲,方法中傳遞的是引用;
只是方法中如果對對象(變量)作出了改變,改變的是引用(指向了另一個地址)或者是自身的實例數據
package Test01;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Test {
public static void main(String[] args) {
HashMap<String,Object> hashMap = new HashMap<String, Object>();
User user = new User();
user.setAge("18");
user.setName("hhh");
hashMap.put("userKey", user);
user.setAge("20");
int i =100;
hashMap.put("i", i);
i=200;
System.out.println("原始map:"+hashMap);
}
輸出:
原始map:{userKey=User{age=‘20’, name=‘hhh’}, i=100}
過程:
1). HashMap和User類加載實例化後,在Java堆中存儲了實例數據,在棧(實際是main棧幀的局部變量表,可參考Java內存區域)中存儲對應的對象引用hashMap、user。
2).執行hashMap.put(“userKey”, user);hashMap對象實際存儲的是對象引用user,該引用與棧中的引用都指向同一塊java堆的內存地址(同一個user對象)
3).執行user.setAge(“20”);修改了user的實例數據,由於同一個引用,所以hashMap裏user的數據也會改變。
4).100和200作爲int字面量,在Test類加載後,已經存儲在方法區的運行時常量池,當執行int i =100;實際是將存儲在棧中的i指向常量池的100,
5). 執行hashMap.put(“i”, i);存儲在hashMap實例對象裏的i和棧中的i一樣,都是指向常量池中的100
6). 執行 i=200;只是將棧中的i重新指向了200,而hashMap裏的i還是指向常量池的100;如圖:
不想寫了,直接看例子吧
例子1:
public class tttMethod {
public int tInt(int i) {
i=2;
return i;
}
}
package Test01;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class GGGG {
public static void main(String[] args) {
int i =100;
tttMethod tttMethod = new tttMethod();
//testInt
tttMethod.tInt(i);
System.out.println("---方法不接受返回值i:"+i);
i = tttMethod.tInt(i);
System.out.println("---方法接受返回值i:"+i);
}
}
輸出:
—方法不接受返回值i:100
—方法接受返回值i:2
過程:
執行tttMethod.tInt(i);時,在tInt的棧幀中,i指向常量池的100;
當在方法中改變i=2,是tInt的棧幀的i改變了指向。
當方法執行結束,tInt棧幀出棧。而main棧幀中的i依舊指向的是100;
當i = tttMethod.tInt(i);時,main棧幀中的i就改變了指向,指向了常量池的2.
例子2:
public class tttMethod {
public HashMap<String,Object> tReturnMethod(HashMap<String, Object> hashMap1) {
hashMap1.put("oooo", "tReturnMethod");
return hashMap1;
}
public void newMethod(HashMap<String, Object> hashMap2) {
hashMap2=new HashMap<String, Object>();
hashMap2.put("oooo", "newMethod");
}
public HashMap<String,Object> newReturnMethod(HashMap<String, Object> hashMap3) {
hashMap3=new HashMap<String, Object>();
hashMap3.put("oooo", "newReturnMethod");
return hashMap3;
}
}
package Test01;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class GGGG {
public static void main(String[] args) {
HashMap<String,Object> hashMap = new HashMap<String, Object>();
hashMap.put("A","aaa");
tttMethod tttMethod = new tttMethod();
// tttMethod.tReturnMethod(hashMap);
hashMap = tttMethod.tReturnMethod(hashMap);
System.out.println("---不新建有返回hashMap修改:"+hashMap); //{A=aaa, oooo=tReturnMethod}
// hashMap = tttMethod.tReturnMethod(hashMap);
// System.out.println("---不新建有返回hashMap修改:"+hashMap); //{A=aaa, oooo=tReturnMethod}
// tttMethod.newMethod(hashMap);
// System.out.println("---新建無返回hashMap後修改:"+hashMap); //{A=aaa}
// hashMap = tttMethod.newReturnMethod(hashMap);
// System.out.println("---新建有返回hashMap後修改:"+hashMap); //{oooo=newReturnMethod}
}
}
輸出如代碼後面註釋所示。
過程:
main棧幀中hashMap指向堆中的HashMap實例數據
調用 tttMethod.tReturnMethod(hashMap);在tReturnMethod棧幀中hashMap1指向同一個堆中的
HashMap實例數據;
方法中hashMap1.put(“oooo”, “tReturnMethod”);改變了HashMap實例數據,所以main棧幀中的
HashMap實例數據也改變了,所以輸出{A=aaa, oooo=tReturnMethod}
當執行tttMethod.newMethod(hashMap);在newMethod棧幀hashMap2原本指向同一個HashMap實例數據
當在方法中hashMap2=new HashMap<String, Object>();在堆內存新開闢塊內存,hashMap2指向新開闢的內存
main棧幀中hashMap一直指向原來的HashMap實例數據,所以輸出{A=aaa}
同理,hashMap = tttMethod.newReturnMethod(hashMap);也一樣,只是最後main棧幀中hashMap指向了新new的內存