java基本數據類型傳遞與引用傳遞區別詳解

Java的值傳遞和引用傳遞在面試中通常都會都被涉及到,今天咱們就來聊聊這個問題,首先咱們必須認識到這個問題通常是相對函數而言的,也就是java中的方法參數,那麼咱們先來回顧一下在程序設計語言中有關參數傳遞給方法(或函數)的兩個專業術語:java

  • 按值調用(call by value)面試

  • 按引用調用(call by reference)函數

所謂的按值調用表示方法接收的是調用着提供的值,而按引用調用則表示方法接收的是調用者提供的變量地址(若是是C語言的話來講就是指針啦,固然java並無指針的概念)。這裏咱們須要注意的是一個方法能夠修改傳遞引用所對應的變量值,而不能修改傳遞值調用所對應的變量值,這句話至關重要,這是按值調用與引用調用的根本區別,固然若是還不理解,不要緊,下面就要圖文並茂的完全分析啦。this

前面咱們說過java中並不存在引用調用,這點是沒錯的,由於java程序設計語言確實是採用了按值調用,即call by value。也就是說方法獲得的是全部參數值的一個拷貝,方法並不能修改傳遞給它的任何參數變量的內容。下面咱們來看一個例子:spa

 

[java]  view plain  copy
 
 print?
  1. package com.zejian.test;  
  2. /** 
  3.  * java中的按值調用 
  4.  * @author zejian 
  5.  */  
  6. public class CallByValue {  
  7.       
  8.     private static int x=10;  
  9.       
  10.     public static void updateValue(int value){  
  11.         value = 3 * value;  
  12.     }  
  13.       
  14.     public static void main(String[] args) {  
  15.         System.out.println("調用前x的值:"+x);  
  16.         updateValue(x);  
  17.         System.out.println("調用後x的值:"+x);  
  18.     }  
  19.       
  20. }  

 

運行程序,結果以下:.net

調用前x的值:10設計

調用後x的值:10指針

能夠看到x的值並無變化,接下來咱們一塊兒來看一下具體的執行過程:對象

 

分析:blog

1)value被初始化爲x值的一個拷貝(也就是10)

2)value被乘以3後等於30,但注意此時x的值仍爲10!

3)這個方法結束後,參數變量value再也不使用,被回收。

結論:當傳遞方法參數類型爲基本數據類型(數字以及布爾值)時,一個方法是不可能修改一個基本數據類型的參數。

固然java中除了基本數據類型還有引用數據類型,也就是對象引用,那麼對於這種數據類型又是怎麼樣的狀況呢?咱們仍是同樣先來看一個例子:

聲明一個User對象類型:

[java]  view plain  copy
 
 print?
  1. package com.zejian.test;  
  2. public class User {  
  3.     private String name;  
  4.     private int age;  
  5.     public User(String name, int age) {  
  6.         this.name=name;  
  7.         this.age=age;  
  8.     }  
  9.     public String getName() {  
  10.         return name;  
  11.     }  
  12.     public void setName(String name) {  
  13.         this.name = name;  
  14.     }  
  15.     public int getAge() {  
  16.         return age;  
  17.     }  
  18.     public void setAge(int age) {  
  19.         this.age = age;  
  20.     }  
  21. }  

執行類以下:

 

[java]  view plain  copy
 
 print?
  1. package com.zejian.test;  
  2. /** 
  3.  * java中的按值調用 
  4.  * @author zejian 
  5.  */  
  6. public class CallByValue {  
  7.     private static User user=null;  
  8.     public static void updateUser(User student){  
  9.         student.setName("Lishen");  
  10.         student.setAge(18);  
  11.     }  
  12.       
  13.       
  14.     public static void main(String[] args) {  
  15.         user = new User("zhangsan",26);  
  16.         System.out.println("調用前user的值:"+user.toString());  
  17.         updateUser(user);  
  18.         System.out.println("調用後user的值:"+user.toString());  
  19.     }  
  20. }  

 

運行結果以下:

調用前user的值:User [name=zhangsan, age=26]

調用後user的值:User [name=Lishen, age=18]

很顯然,User的值被改變了,也就是說方法參數類型若是是引用類型的話,引用類型對應的值將會被修改,下面咱們來分析一下這個過程:

過程分析:

1)student變量被初始化爲user值的拷貝,這裏是一個對象的引用。

2)調用student變量的set方法做用在這個引用對象上,user和student同時引用的User對象內部值被修改。

3)方法結束後,student變量再也不使用,被釋放,而user仍是沒有變,依然指向User對象。

結論:當傳遞方法參數類型爲引用數據類型時,一個方法將修改一個引用數據類型的參數所指向對象的值。

雖然到這裏兩個數據類型的傳遞都分析完了,也明白的基本數據類型的傳遞和引用數據類型的傳遞區別,前者將不會修改原數據的值,然後者將會修改引用所指向對象的值。可經過上面的實例咱們可能就會以爲java同時擁有按值調用和按引用調用啊,惋惜的是這樣的理解是有誤導性的,雖然上面引用傳遞表面上體現了按引用調用現象,可是java中確實只有按值調用而沒有按引用調用。到這裏估計很多人都蒙逼了,下面咱們經過一個反例來講明(回憶一下開頭咱們所說明的按值調用與按引用調用的根本區別)。

[java]  view plain  copy
 
 print?
  1. package com.zejian.test;  
  2. /** 
  3.  * java中的按值調用 
  4.  * @author zejian 
  5.  */  
  6. public class CallByValue {  
  7.     private static User user=null;  
  8.     private static User stu=null;  
  9.       
  10.     /** 
  11.      * 交換兩個對象 
  12.      * @param x 
  13.      * @param y 
  14.      */  
  15.     public static void swap(User x,User y){  
  16.         User temp =x;  
  17.         x=y;  
  18.         y=temp;  
  19.     }  
  20.       
  21.       
  22.     public static void main(String[] args) {  
  23.         user = new User("user",26);  
  24.         stu = new User("stu",18);  
  25.         System.out.println("調用前user的值:"+user.toString());  
  26.         System.out.println("調用前stu的值:"+stu.toString());  
  27.         swap(user,stu);  
  28.         System.out.println("調用後user的值:"+user.toString());  
  29.         System.out.println("調用後stu的值:"+stu.toString());  
  30.     }  
  31. }  

咱們經過一個swap函數來交換兩個變量user和stu的值,在前面咱們說過,若是是按引用調用那麼一個方法能夠修改傳遞引用所對應的變量值,也就是說若是java是按引用調用的話,那麼swap方法將可以實現數據的交換,而實際運行結果是:

 

調用前user的值:User [name=user, age=26]

調用前stu的值:User [name=stu, age=18]

調用後user的值:User [name=user, age=26]

調用後stu的值:User [name=stu, age=18]

咱們發現user和stu的值並無發生變化,也就是方法並無改變存儲在變量user和stu中的對象引用。swap方法的參數x和y被初始化爲兩個對象引用的拷貝,這個方法交換的是這兩個拷貝的值而已,最終,所作的事都是白費力氣罷了。在方法結束後x,y將被丟棄,而原來的變量user和stu仍然引用這個方法調用以前所引用的對象。

這個過程也充分說明了java程序設計語言對對象採用的不是引用調用,其實是對象引用進行的是值傳遞,固然在這裏咱們能夠簡單理解爲這就是按值調用和引用調用的區別,並且必須明白即便java函數在傳遞引用數據類型時,也只是拷貝了引用的值罷了,之因此能修改引用數據是由於它們同時指向了一個對象,但這仍然是按值調用而不是引用調用。

總結:

    • 一個方法不能修改一個基本數據類型的參數(數值型和布爾型)。

    • 一個方法能夠修改一個引用所指向的對象狀態,但這仍然是按值調用而非引用調用。

    • 上面兩種傳遞都進行了值拷貝的過程。

相關文章
相關標籤/搜索