解析java基本數(shù)據(jù)類型傳遞與引用傳遞區(qū)別
java中方法參數(shù)傳遞方式是按值傳遞。
如果參數(shù)是基本類型,傳遞的是基本類型的字面量值的拷貝。
如果參數(shù)是引用類型,傳遞的是該參量所引用的對象在堆中地址值的拷貝。
java的值傳遞和引用傳遞在面試中一般都會都被涉及到,今天我們就來聊聊這個問題,首先我們必須認識到這個問題一般是相對函數(shù)而言的,也就是java中的方法參數(shù),那么我們先來回顧一下在程序設(shè)計語言中有關(guān)參數(shù)傳遞給方法(或函數(shù))的兩個專業(yè)術(shù)語:
按值調(diào)用(call by value)
按引用調(diào)用(call by reference)
所謂的按值調(diào)用表示方法接收的是調(diào)用著提供的值,而按引用調(diào)用則表示方法接收的是調(diào)用者提供的變量地址(如果是C語言的話來說就是指針啦,當(dāng)然java并沒有指針的概念)。這里我們需要注意的是一個方法可以修改傳遞引用所對應(yīng)的變量值,而不能修改傳遞值調(diào)用所對應(yīng)的變量值,這句話相當(dāng)重要,這是按值調(diào)用與引用調(diào)用的根本區(qū)別,當(dāng)然如果還不理解,沒關(guān)系,下面就要圖文并茂的徹底分析啦。
前面我們說過java中并不存在引用調(diào)用,這點是沒錯的,因為java程序設(shè)計語言確實是采用了按值調(diào)用,即call by value。也就是說方法得到的是所有參數(shù)值的一個拷貝,方法并不能修改傳遞給它的任何參數(shù)變量的內(nèi)容。下面我們來看一個例子:
package com.zejian.test;
/**
* java中的按值調(diào)用
* @author zejian
*/
public class CallByValue {
private static int x=10;
public static void updateValue(int value){
value = 3 * value;
}
public static void main(String[] args) {
System.out.println("調(diào)用前x的值:"+x);
updateValue(x);
System.out.println("調(diào)用后x的值:"+x);
}
運行程序,結(jié)果如下:
調(diào)用前x的值:10
調(diào)用后x的值:10
可以看到x的值并沒有變化,接下來我們一起來看一下具體的執(zhí)行過程:

分析:
1)value被初始化為x值的一個拷貝(也就是10)
2)value被乘以3后等于30,但注意此時x的值仍為10!
3)這個方法結(jié)束后,參數(shù)變量value不再使用,被回收。
結(jié)論:當(dāng)傳遞方法參數(shù)類型為基本數(shù)據(jù)類型(數(shù)字以及布爾值)時,一個方法是不可能修改一個基本數(shù)據(jù)類型的參數(shù)。
當(dāng)然java中除了基本數(shù)據(jù)類型還有引用數(shù)據(jù)類型,也就是對象引用,那么對于這種數(shù)據(jù)類型又是怎么樣的情況呢?我們還是一樣先來看一個例子:
聲明一個User對象類型:
執(zhí)行類如下:
package com.zejian.test;
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
執(zhí)行類如下:
package com.zejian.test;
/**
* java中的按值調(diào)用
* @author zejian
*/
public class CallByValue {
private static User user=null;
public static void updateUser(User student){
student.setName("Lishen");
student.setAge(18);
}
public static void main(String[] args) {
user = new User("zhangsan",26);
System.out.println("調(diào)用前user的值:"+user.toString());
updateUser(user);
System.out.println("調(diào)用后user的值:"+user.toString());
}
運行結(jié)果如下:
調(diào)用前user的值:User [name=zhangsan, age=26]
調(diào)用后user的值:User [name=Lishen, age=18]
很顯然,User的值被改變了,也就是說方法參數(shù)類型如果是引用類型的話,引用類型對應(yīng)的值將會被修改,下面我們來分析一下這個過程:

過程分析:
1)student變量被初始化為user值的拷貝,這里是一個對象的引用。
2)調(diào)用student變量的set方法作用在這個引用對象上,user和student同時引用的User對象內(nèi)部值被修改。
3)方法結(jié)束后,student變量不再使用,被釋放,而user還是沒有變,依然指向User對象。
結(jié)論:當(dāng)傳遞方法參數(shù)類型為引用數(shù)據(jù)類型時,一個方法將修改一個引用數(shù)據(jù)類型的參數(shù)所指向?qū)ο蟮闹怠?/p>
雖然到這里兩個數(shù)據(jù)類型的傳遞都分析完了,也明白的基本數(shù)據(jù)類型的傳遞和引用數(shù)據(jù)類型的傳遞區(qū)別,前者將不會修改原數(shù)據(jù)的值,而后者將會修改引用所指向?qū)ο蟮闹???赏ㄟ^上面的實例我們可能就會覺得java同時擁有按值調(diào)用和按引用調(diào)用啊,可惜的是這樣的理解是有誤導(dǎo)性的,雖然上面引用傳遞表面上體現(xiàn)了按引用調(diào)用現(xiàn)象,但是java中確實只有按值調(diào)用而沒有按引用調(diào)用。到這里估計不少人都蒙逼了,下面我們通過一個反例來說明(回憶一下開頭我們所說明的按值調(diào)用與按引用調(diào)用的根本區(qū)別)。
package com.zejian.test;
/**
* java中的按值調(diào)用
* @author zejian
*/
public class CallByValue {
private static User user=null;
private static User stu=null;
/**
* 交換兩個對象
* @param x
* @param y
*/
public static void swap(User x,User y){
User temp =x;
x=y;
y=temp;
}
public static void main(String[] args) {
user = new User("user",26);
stu = new User("stu",18);
System.out.println("調(diào)用前user的值:"+user.toString());
System.out.println("調(diào)用前stu的值:"+stu.toString());
swap(user,stu);
System.out.println("調(diào)用后user的值:"+user.toString());
System.out.println("調(diào)用后stu的值:"+stu.toString());
}
}
我們通過一個swap函數(shù)來交換兩個變量user和stu的值,在前面我們說過,如果是按引用調(diào)用那么一個方法可以修改傳遞引用所對應(yīng)的變量值,也就是說如果java是按引用調(diào)用的話,那么swap方法將能夠?qū)崿F(xiàn)數(shù)據(jù)的交換,而實際運行結(jié)果是:
調(diào)用前user的值:User [name=user, age=26]
調(diào)用前stu的值: User [name=stu, age=18]
調(diào)用后user的值:User [name=user, age=26]
調(diào)用后stu的值: User [name=stu, age=18]
我們發(fā)現(xiàn)user和stu的值并沒有發(fā)生變化,也就是方法并沒有改變存儲在變量user和stu中的對象引用。swap方法的參數(shù)x和y被初始化為兩個對象引用的拷貝,這個方法交換的是這兩個拷貝的值而已,最終,所做的事都是白費力氣罷了。在方法結(jié)束后x,y將被丟棄,而原來的變量user和stu仍然引用這個方法調(diào)用之前所引用的對象。

這個過程也充分說明了java程序設(shè)計語言對對象采用的不是引用調(diào)用,實際上是對象引用進行的是值傳遞,當(dāng)然在這里我們可以簡單理解為這就是按值調(diào)用和引用調(diào)用的區(qū)別,而且必須明白即使java函數(shù)在傳遞引用數(shù)據(jù)類型時,也只是拷貝了引用的值罷了,之所以能修改引用數(shù)據(jù)是因為它們同時指向了一個對象,但這仍然是按值調(diào)用而不是引用調(diào)用。
總結(jié):
一個方法不能修改一個基本數(shù)據(jù)類型的參數(shù)(數(shù)值型和布爾型)。
一個方法可以修改一個引用所指向的對象狀態(tài),但這仍然是按值調(diào)用而非引用調(diào)用。
上面兩種傳遞都進行了值拷貝的過程。
以上所述是小編給大家介紹的java基本數(shù)據(jù)類型傳遞與引用傳遞區(qū)別詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
基于SpringBoot應(yīng)用監(jiān)控Actuator安全隱患及解決方式
這篇文章主要介紹了SpringBoot應(yīng)用監(jiān)控Actuator安全隱患及解決方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
java 實現(xiàn)截取字符串并按字節(jié)分別輸出實例代碼
這篇文章主要介紹了java 實現(xiàn)截取字符串并按字節(jié)分別輸出實例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
java集合中HashSet LinkedHashSet TreeSet三者異同面試精講
這篇文章主要為大家介紹了java集合中HashSet LinkedHashSet TreeSet三者異同面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10
Java使用ffmpeg和mencoder實現(xiàn)視頻轉(zhuǎn)碼
這篇文章主要為大家詳細介紹了Java使用ffmpeg和mencoder實現(xiàn)視頻轉(zhuǎn)碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12
淺談java中異步多線程超時導(dǎo)致的服務(wù)異常
下面小編就為大家?guī)硪黄獪\談java中異步多線程超時導(dǎo)致的服務(wù)異常。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-06-06
mybatis教程之動態(tài)sql語句_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了mybatis教程之動態(tài)sql語句,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09

