關(guān)于java程序運行時各種變量在內(nèi)存的存儲知識先看這里》》
變量賦值:
對于基本數(shù)據(jù)類型變量:即int, short, long, byte, float, double, boolean, char類型的變量。這種類型變量在內(nèi)存中直接存放數(shù)據(jù)。變量之間賦值如int a=b;直接傳數(shù)據(jù)。a++,不影響b的數(shù)據(jù)。
對象變量:對象變量在內(nèi)存中存放的是引用。這個引用值指向堆中的對象。Object c=b;傳的是引用值,他們指向同一個堆對象。

如上圖,age是int變量,具體數(shù)據(jù)值如9,就放在那里,而owner是對象變量,它放的是引用,指向堆里owner對象。
下兩圖是方法調(diào)用時在棧幀里的局部變量表里的變量和參數(shù),圖示示例了兩種引用對象的方式。
(詳細(xì)java程序運行時的棧幀內(nèi)存結(jié)構(gòu)看這里》》)

此圖示例了通過句柄池引用方式指向堆對象的方式。

此圖示例了直接指向堆中對象的方式。
兩種方式各有優(yōu)勢,第一種方式在對象被GC遷移時只需改變句柄池中的實例指針即可,而不用改變reference引用本身的值。第二種方式就是訪問速度快。目前HotSpot虛擬機就采用的第二種方式。
下面用個例子來說明:
下面是個Dog類,用來測試時產(chǎn)生對象,進(jìn)行引用傳遞

mName和mYear是類的實例變量
下面是傳遞變量測試類,其中也有變量賦值測試然后打印出來

主測試類

結(jié)果:

第1行和第2行對比:基礎(chǔ)類型變量之間賦值傳值,互相不影響;對象變量之間賦值傳引用,mainDog和mainDog2指向同一個堆內(nèi)的對象。mainDog2把對象名字改變后,mainDog打印出來也是改變后的名字。
第2、3、4、5行之間對比:方法參數(shù)的傳遞,基礎(chǔ)型參數(shù)變量傳值,和外面的基礎(chǔ)類型實例變量互不影響。方法的對象類型參數(shù)傳遞時傳引用,和外面的實例變量引用值相同,指向堆內(nèi)同一個對象。此時堆內(nèi)只有一個dog。
第5、6、7行之間對比:方法內(nèi)的對象參數(shù)或?qū)ο缶植孔兞扛淖円弥禃r,不影響外面的對象實例變量。此時方法內(nèi)mainDog對象參數(shù)變量指向的堆對象和實例對象變量mainDog指向的堆對象不同。堆內(nèi)曾有過2個dog。
如何 讓對象變量之間賦值傳值而不是引用呢?
Dog dog=new dog();
Dog dog2=dog;
如要達(dá)到dog2是個獨立的堆對象,但屬性要與dog一模一樣;
Dog dog2=dog.clone();需要類實現(xiàn)clone接口;
設(shè)計模式中有個原型模式,就是clone;原型模式