JAVA中有兩種類型,基本類型和引用類型。但在函數傳參的過程中,基本類型和引用傳遞的到底是什麼呢?
在JVM中,基本類型中的數值使用一塊內存來保存。引用類型由兩塊內存來保存,一塊內存中裝的是真實的數據,就是引用的對象,另一塊內存中裝的是指向類數據的引用,存儲的是對象的內存地址。jvm需要通過此引用找到該對象的方法表,類型信息。其中類型信息包括類型基本信息,常量池,字段信息,方法信息,類變量信息,指向class的引用,指向classloader的引用。這些數據都存放在方法區。
在函數傳參的過程中,基本類型只會傳遞數值,那麼引用類型傳遞的真實的數據,還是指向該內存的地址呢?
下面的文章引用自 java中函數是值傳遞還是引用傳遞?
相信有些同學跟我一樣,曾經對這個問題很疑惑。在網上也看了一些別人說的觀點,評論不一。有說有值傳遞和引用傳遞兩種,也有說只有值傳遞的,這裏只說下個人見解
先看一個例子
public class Test1 { public static void main(String[] args) { int a = 10; changeNum(a); System.out.println("main a=" + a); } static void changeNum(int a) { a = 100; System.out.println("changeNum a=" + a); } }
結果:
changeNum a=100
main a=10
說明對於基本的數值類型其實傳遞的是一份數值的拷貝,傳入函數之後跟原來的值就沒有關係了,在函數中改變這個數的值也不會影響到原來的值。
再看一個例子
public class P { String name = "P"; public P(String name) { this.name = name; } @Override public String toString() { return name; } } public class Test { static P p1 = new P("p1"); public static void main(String[] args) { P p = new P("P"); System.out.println("before change p:" + p.toString); changeObj(p); System.out.println("after change p:" + p.toString()); } static void changeObj(P p) { p = new P("pp"); System.out.println("change p:" + p.toString()); //p = p1; //System.out.println(p.toString()); } }
這個例子中的運行結果會是什麼呢?
在這個例子中傳入的是一個對象類型的數據。
我們先來猜想一下:如果傳入的是一個對象的引用,在函數中改變了這個引用所指向的對象,那麼外部的引用"p"應該是指向了新創建的P("pp")的對象纔對
所以猜想的結果是:
before change p:P
change p:pp
after change p:pp
那讓我們來實際運行一下看看結果,實際的結果是:
before change p:P
change p:pp
after change p:P
想猜想的不一樣!!!
這就讓我們很疑惑了,爲什麼函數沒有改變引用所指向對象呢?
其實是這樣的,首先要理解“=”賦值操作的意義,
對於基本類型來說“=”賦值操作是直接改變內存地址上的值,
而對引用類型來說“=”賦值其實是改變引用變量所指向的內存地址。
賦值操作後
引用的賦值並沒有對原來的對象造成影響,"hello"對象仍然是存在的,只是str又指向了新的"world"對象
理解了賦值操作後,現在來說下函數的參數傳遞
函數的參數實際上就是函數內部的一個局部變量,從外部傳值給這個參數實際上就是一個賦值的過程。
來看看第一個例子,傳一個定義一個int類型名稱爲a的形式參數,其實完全可以把名稱改爲b
然後把外部變量a的值傳遞給函數的變量,就是賦值。基本類型的賦值就是把外部a變量的10賦值給函數變量a,所以這其實是兩個變量,兩者之間沒有任何關係,
所以對函數內部變量的改變也不會對外部的變量造成影響。
再來說下引用類型的傳遞,其實是一個道理。
在傳遞的時候是把一個對象的內存地址賦值給函數內部的引用類型的局部變量
如上圖所示,兩個變量是指向同一個對象的。
在第二個例子中,我們在函數內部新創建了一個對象,並重新賦值給內部變量p,其實是改變了內部變量的引用所指向的對象,如下圖所示
所以對外部的p變量是沒有影響的。
總結:
函數參數傳遞其實是一個賦值的過程,基本類型傳遞的是數值,引用類型傳遞的引用對象的內存地址。
另外一點要特別注意,函數的參數其實是函數內部的局部變量。不要跟外部變量混淆
以上內容均爲原創,轉載請註明出外 http://www.cnblogs.com/taixuyingcai/p/6373423.html