深入探究Java編程是值傳遞還是引用傳遞

文章目的:驗證Java語言到底是值傳遞還是引用傳遞以及Java參數(shù)傳遞的實現(xiàn)原理.
問題引入:
先閱讀代碼段:
public static void main(String[] args){
Person p=new Person("張三");
f(p);
System.out.println("實參:"+p);
}
public static void f(Person p){
p.name="李四";
System.out.println("形參:"+p);
}運行結(jié)果:
形參:Person{name=“李四”}
實參:Person{name=“李四”}
我們將一個對象變量傳遞到方法中,然后在方法內(nèi)修改對象的屬性,打印實參和形參,從表面上看,實參形參的值都被修改了.難道Java也支持引用傳遞嗎?
答案是:Java語言只支持值傳遞,不支持引用傳遞.
在驗證Java參數(shù)傳遞方式之前,我們先要明白函數(shù)值傳遞和引用傳遞的區(qū)別.
- 值傳遞(pass by value)是指在調(diào)用函數(shù)時將實際參數(shù)復(fù)制一份傳遞到函數(shù)中,這樣在函數(shù)中如果對參數(shù)進(jìn)行修改,將不會影響到實際參數(shù)。
- 引用傳遞(pass by reference)是指在調(diào)用函數(shù)時將實際參數(shù)的地址直接傳遞到函數(shù)中,那么在函數(shù)中對參數(shù)所進(jìn)行的修改,將影響到實際參數(shù)。
可以看出值傳遞和引用傳遞的區(qū)別在于對形參的修改會不會影響到實參
1.基本數(shù)據(jù)類型的參數(shù)傳遞
我們將一個基本數(shù)據(jù)類型傳遞到方法中,然后在方法中修改形參的值,發(fā)現(xiàn)形參的修改并沒有影響到實參.
public static void main(String[] args){
int a=1;
f(p);
System.out.println("實參:"+a);
}
public static void f(int a){
a=2;
System.out.println("形參:"+a);
}2.引用數(shù)據(jù)類型的參數(shù)傳遞
在問題引入的例子中,看似形參的修改影響到了實參,但是只要我們創(chuàng)建一個新對象,并賦值給形參,此時再打印實參和形參,兩者互不影響.說明Java并不符合引用傳遞.
public static void main(String[] args){
Person p=new Person("張三");
f(p);
System.out.println("實參:"+p);
}
public static void f(Person p){
p=new Person("李四");
System.out.println("形參:"+p);
}3.原理
我們要明白為什么會發(fā)生這些現(xiàn)象,就要理解Java背后的基本原理:
JVM劃分了很多塊區(qū)域,我們創(chuàng)建的對象就放在堆中,而基本數(shù)據(jù)類型和局部變量都放在棧中.當(dāng)傳遞基本數(shù)據(jù)類型時,是將數(shù)據(jù)創(chuàng)建了一個副本傳遞到方法中,所以實參不會受到形參修改的影響,如圖:

由于對象是放在堆區(qū)的,所以我們只能使用對象的引用來操作這個對象.
當(dāng)對象引用傳遞給方法時,其實是創(chuàng)建了一個引用副本,同時指向同一個對象,通過形參引用操作對象時,就好像實參發(fā)生了變化,其實對象內(nèi)容改變了,但是對象變量沒有改變,實參本身是沒有改變的.因此引入問題中的例子就不難理解了.

當(dāng)我們將形參重新賦值的時候,實參不會受到任何影響,此時,實參和形參已經(jīng)指向了兩個不同的對象.
所以說,Java只支持值傳遞.
到此這篇關(guān)于深入探究Java編程是值傳遞還是引用傳遞的文章就介紹到這了,更多相關(guān)Java值傳遞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 數(shù)據(jù)結(jié)構(gòu)鏈表操作實現(xiàn)代碼
這篇文章主要介紹了Java 數(shù)據(jù)結(jié)構(gòu)鏈表操作的相關(guān)資料,并附實例代碼,需要的朋友可以參考下2016-10-10
Java中StringRedisTemplate和RedisTemplate的區(qū)別及使用方法
本文主要介紹了Java中StringRedisTemplate和RedisTemplate的區(qū)別及使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
Maven?項目用Assembly打包可執(zhí)行jar包的方法
這篇文章主要介紹了Maven?項目用Assembly打包可執(zhí)行jar包的方法,該方法只可打包非spring項目的可執(zhí)行jar包,需要的朋友可以參考下2023-03-03
一篇文章帶你了解jdk1.8新特性--為什么使用lambda表達(dá)式
Lambda是一個匿名函數(shù),我們可以把Lambda表達(dá)式理解為是一段可以傳遞的代碼,本篇文章就帶你了解,希望能給你帶來幫助2021-08-08

