一. 首先java中的基礎數據類型 byte,short,int,long,float,double,boolean,char
1. 通過基本數據類型聲明的局部都是存儲java虛擬機棧當中
2. 非基本數據類型,存儲於java 堆內存當中
二 基本類型 和 引用類型的不同之處
int num = 10; String str = "hello";
1. 如圖所示,num是基本類型,值就直接保存在變量中。而str是引用類型,變量中保存的只是實際對象的地址。一般稱這種變量為"引用",引用指向實際對象,實際對象中保存着內容。
三 賦值運算符(=)的作用
num = 20;
str = "java";
1. 對於基本類型 num ,賦值運算符會直接改變變量的值,原來的值被覆蓋掉。
2. 對於引用類型 str,賦值運算符會改變引用中所保存的地址,原來的地址被覆蓋掉。但是原來的對象不會被改變(重要)。
3. 如上圖所示,"hello" 字符串對象沒有被改變。(沒有被任何引用所指向的對象是垃圾,會被垃圾回收器回收)

四. 代碼與結果
public class ComboBox { public static void main(String[] args) throws Exception { int a = 100000; funA(a);// 傳遞的基本數據類型 System.out.println("a = " + a); Integer b = new Integer(100000); funB(b);// 傳遞非基本數據類型(包裝類) System.out.println("b = " + b); Integer c = new Integer(100000); funC(c);// 同B System.out.println("c = " + c); } public static void funA(int a) { a = 9999999; } public static void funB(Integer b) { b = 9999999; } private static void funC(Integer c) throws Exception { //JDK未提供Integer修改vlaue值的方式,通過反射修改 Field field = Integer.class.getDeclaredField("value"); field.setAccessible(true); field.set(c, 999999); } } a = 100000 b = 100000 c = 999999
FunA鏈路:

FunB鏈路:

FunC鏈路圖

五. 總計與分析
局部變量和方法參數在jvm中的儲存方法是相同的,都是在棧上開辟空間來儲存的,隨着進入方法開辟,退出方法回收。以32位JVM為例,boolean/byte/short/char/int/float以及引用都是分配4字節空間,long/double分配8字節空間。
在JVM內存模型中有,stack和heap的存在,但是更准確的說,是每個線程都分配一個獨享的stack,所有線程共享一個heap。對於每個方法的局部變量來說,是絕對無法被其他方法,甚至其他線程的同一方法所訪問到的,更無法修改。
當我們在方法中聲明一個 int i = 0,或者 Object obj = null 時,僅僅涉及stack,不影響到heap,當我們 new Object() 時,會在heap中開辟一段內存並初始化Object對象。當我們將這個對象賦予obj變量時,僅僅是stack中代表obj的那4個字節變更為這個對象的地址。
上面中的傳遞?FunA傳遞了棧內存具體的值 num = 10000(FunA stack中存一份副本,形參), FunB傳遞了棧內num對象的地址 num = 0x000002(FunB stack中存一份副本,形參), FunC和FunB 一樣中傳遞了棧內num對象的地址 num = 0x000002(但是對目標對象堆內存中的值做了修改)
如果是數據類型,會直接當棧中存儲的基本值傳遞給了形式參數復制一份。如果是非基本數據類型,是把實際參數的引用的地址復制了一份,傳遞給了形式參數,簡單說就是把實參對象引用的地址當做值傳遞給了形式參數。

