Java 傳參是值傳遞還是參考傳遞?這個問題很基礎,但是許多人都有點懵
首先我們得了解關於參數的幾個概念
##形式參數: 定義函數時使用的參數,用來接收函數傳入參數,例如我們寫個函數,函數中的參數為形式參數
public void test(String str) { //str为形式参数 System.out.println(str); }
實際參數:我們呼叫函數時,函數名稱後面括號中的參數稱為實際參數,必須有確定的值,如下面例子所示
public static void main(String[] args) { A a = new A(); a.test("小 明"); //"小 明"则为实际参数 }可以發現,當呼叫一個有參函數的時候,會把實際參數傳遞給形式參數。 這種傳遞的過程的參數一般有2種情況
值傳遞和引用傳遞。
複製一份傳遞到函數中,函數內部對參數內部進行修改不會影響實際參數,即建立副本,不會影響原生物件
不創建副本,會影響原生物件
基本資料型別和引用資料型別,除了8種基本資料型別以外都是引用資料型別,分別是byte,short ,int,long,char,boolean,float,double
public class TestBasic { public static void main(String[] args) { int num1 = 10; int num2 = 20; change(num1, num2); System.out.println("=============="); System.out.println("num1 = " + num1); System.out.println("num2 = " + num2); } public static void change(int param1, int param2) { System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); param1 = 333; param2 = 444; System.out.println("after change...."); System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); } }
param1 = 10我們可以發現,change()方法內對變數重新賦值,並未改變變數num1和num2的值,param2 = 20
after change....
param1 = 333
param2 = 444
==============
num1 = 10
num2 = 20
改變的只是change()方法內的num1和num2的副本。 我們需要知道,基本資料型別在記憶體中只有一塊儲存空間,分配在堆疊stack。
Java傳參的型別如果是基本資料型別,是值傳遞。
傳參的型別:引用資料型別public class TestQuote { public static void main(String[] args) { String str = "小明"; StringBuilder str2 = new StringBuilder("今天天气好"); change(str,str2); System.out.println("=============="); System.out.println("str = " + str); System.out.println("str2 = " + str2); } public static void change(String param1,StringBuilder param2) { System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); param1= "小张"; param2.append(",我们去钓鱼"); System.out.println("after change...."); System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); } }
param1 = 小明我們發現str變數沒有改變,但是str2變數卻改變了,大家是不是迷惑了:Java傳參的類型如果是引用資料類型,是param2 = 今天天氣好
after change....
param1 = 小張
param2 = 今天天氣好,我們去釣魚
str = 小明
str2 = 今天天氣好,我們去釣魚
值傳遞還是引用傳遞?
其實大家被一堆術語給忽悠了,筆者畫了2張圖,幫助大家理解:before change():after change(): 在Java中,除了基本資料型別以外,其他的都是參考型,引用型別在記憶體中有兩塊儲存空間(一塊在堆疊stack中,一塊在堆heap中)。 如果參數是引用型,傳遞的就是實參所引用的物件在堆疊中位址值的拷貝,這裡所建立的副本是 位址的拷貝。那就有人說了,可是它值變了呀,這明明就是"引用傳遞"嘛? 我們可以換個角度理解,如果我們把堆疊位址當成值,會建立堆疊位址副本(複製堆疊訊框),堆疊位址最終並沒有改變,改變的是堆疊記憶體中的值。這就好比棧地址是鑰匙,我們copy了一把,它能打開保險箱。我們關心的是鑰匙有沒有花紋這種變化,至於打開保險箱後的錢多錢少,我們並不需要關心。 雖然調用完函數後,str2變數值(堆疊中的資料)改變了,但是參數是引用類型,傳遞的實參是堆疊中位址值,這是我們關心的,拷貝的是棧中位址值,最終棧中位址值並沒有改變。所以是符合
值傳遞的定義建立副本,不會影響原生物件。
可能又有人問了,那str變數值為啥沒有改變呢?其實這完全是由於String類別的特殊,我們知道它是不可變的final,這個時候在函數中param1= "小張";其實會隱式創建一個新的String物件,同時堆記憶體中會開啟一個新的記憶體空間,param1指向了這個新開啟的記憶體空間。原始位址str指向的堆記憶體空間中資料沒有任何改變。
以上是Java中為什麼只有值傳遞的詳細內容。更多資訊請關注PHP中文網其他相關文章!