參數傳遞

在Java中參數傳遞主要分爲兩種,一是值傳遞,二是引用傳遞

一、首先我們要知道有哪些數據類型。

       一種是基本數據類型。就是我們熟悉的 byte 、short、int、long、float、double、char、boolean 共八種。

       另一種是引用數據類型。我們平時用關鍵字 class、interface、abstract class 定義的類、接口、抽象類就是一個引用數據類型。

二、值傳遞

      基本數據類型之間的參數傳遞就是值傳遞。但是引用數據類型 String (有且只有String)的參數傳遞也是值傳遞

      值傳遞就是把數據的值,也就是數據的實例傳過來。像C++中普通的參數傳遞一樣,形參中數據的改變並不會對實參造成任何影響。

下面是一個值傳遞的例子:

輸出結果爲:                                          

可以清楚的看見,在init() 中,調用方法前後,num的值並不會發生影響。我們從他們的儲存來看看原因。

init() 和 change() 兩個方法的 num 都儲存在棧中,init()通過參數傳遞將5 傳給change()中的數據,change中數據的改變只改變了自己本身的值而與init中的num無關。

三、引用傳遞

    引用數據類型(除String外)之間的參數傳遞是引用傳遞。所謂引用傳遞當然就是把自己的引用傳過去,而類接口、抽象類的引用都是一個地址,也就是說,引用傳遞傳的就是一個地址(內存中的首地址)。

    下面我們看一個例子。

輸出結果爲:                                                          

在內存中的初始存儲爲:

我們分別創建了兩個Bank對象 b1、b2 ,開始創建結束後,兩者的引用(即指向的在堆中的地址)是不一樣的。

然而當執行 b2 = b1 語句後,b1 的引用賦給了b2,也就是說,b2 指向了b1所指向的內存。如下圖:

因此,當b2調用addMoney()方法時,修改的是 內存“@abc” 中的屬性money的值,最後打印數據資料的時候,也是根據引用找到指向的內存並讀取相應的數據,因此兩者打印出來的都是 60.

四、 String 是個特殊的引用數據

      毫無疑問,String是一個引用數據類型,但是他的參數傳遞確是值傳遞。無論是他的常量對象還是String對象都是如此。

我們先看一個例子吧。

在調用chagne() 方法後,不管是常量對象還是String對象 他的strX的值都沒有發生改變,就是因爲String的參數傳遞採用的是值傳遞的方式。

然而,爲什麼我明明都是值傳遞,當常量對象傳過來的時候,他的值與和它內容相同的常量地址相同,而當我是String對象傳過來的時候卻不相同呢??我們有一個姑且可以這麼記憶的方法:

1. 當你傳過來的值是一個常量對象時,形參中的數據 s 按常量的儲存模式,即 s 的引用爲常量池中“你我都是一塊磚”的儲存地址,那麼自然的,str1 指向的也是常量池中的相同數據,那麼他們的地址當然就是相同的。

2. 當你傳過來的值是一個String對象,形參中的 s 也是按照String對象的儲存方式進行儲存。即先申請一塊空間,再將傳過來的值根據相應的構造方法進行實例化,就跟 new String ("傳過來的值"); 形成的結果一樣,那麼自然的 , s 就不是指向   "哪裏需要往哪裏搬"  ,而是一塊新的內存。

下面有一個關於String儲存的說明。

由於Java自身儲存方式的原因,Java在編譯class文件的時候,會爲這個類中的常量等數據另創一個叫做常量池的內存空間,這個空間中可以存儲基本數據類型,文本字符串(String常量)類型、final、......看下圖

 String  str1 = "你我都是一塊磚";   

  雖然 str1 是一個常量對象,但是他也是一個對象,因此他也有自己的引用和實體。當常量池中  "你我都是一塊磚" 存儲的首地址爲 “@abc”那麼str1 中的引用也就是 @abc 。    傳參是,傳的自然也是他的引用,即 @abc ,但是爲什麼s修改爲 “嘻哈嘻哈過大年” 的時候str1 的值卻沒有變呢?這是因爲,常量池中的數據在程序運行期間在也不允許改變,當s的值發生改變後,他能做的就是修改自己的引用指向新的常量池中的位置,而不是修改自己引用中的值。即下圖:

   由於Java常量池儲存結構的加入,基本數據類型的儲存都是常量池的儲存方式,因而會造成一個現象。

      有             

由於開始 num1 和num2 的值都爲5 ,毫無疑問,他們的引用都是常量池中5的地址。但是num3 不太一樣的是,雖然他開始是指向的是num1 ,但是他的並不指向num1位置,而是同樣指向常量池中的5,只有當num3 的值發生改變,例如改爲10時,常量池中才會開闢出新的空間(如果之前的數據沒有10)儲存10,然後再改變num3的引用。Java這樣做的目的是爲了節省空間。如下圖:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章