java 傳遞引數的兩種方式

TuxedoLinux發表於2018-05-26
java 傳遞引數的兩種方式
Java中沒有指標,所以也沒有引用傳遞了,僅僅有值傳遞不過可以通過物件的方式來實現引用傳遞 類似java沒有多繼承 但可以用多次implements 介面實現多繼承的功能

  值傳遞:方法呼叫時,實際引數把它的值傳遞給對應的形式引數,方法執行中形式引數值的改變不影響實際參 數的值。

  引用傳遞:也稱為傳地址。方法呼叫時,實際引數的引用(地址,而不是引數的值)被傳遞給方法中相對應的形式引數,在方法執行中,對形式引數的操作實際上就是對實際引數的操作,方法執行中形式引數值的改變將會影響實際引數的值。

       a.傳遞值的資料型別:八種基本資料型別和String(這樣理解可以,但是事實上String也是傳遞的地址,只是string物件和其他物件是不同的,string物件是不能被改變的,內容改變就會產生新物件。那麼StringBuffer就可以了,但只是改變其內容。不能改變外部變數所指向的記憶體地址)。
    b.傳遞地址值的資料型別:除String以外的所有複合資料型別,包括陣列、類和介面 
值傳遞的例子:
  1. package com.other.test;  
  2.   
  3. public class Test {  
  4.     public static void change(int i, int j) {   
  5.         int temp = i;   
  6.         i = j;   
  7.         j = temp;  
  8.     }   
  9.   
  10.     public static void main(String[] args) {   
  11.         int a = 3;   
  12.         int b = 4;   
  13.         change(a, b);   
  14.         System.out.println("a=" + a);   
  15.         System.out.println("b=" + b);  
  16.     }  
  17. }  

輸出的結果是 a=3 b=4,傳遞的值並不會改變原值

引用傳遞的例子:(陣列)
  1. package com.other.test;  
  2.   
  3. public class Test {  
  4.     public static void change(int[] counts) {   
  5.         counts[0] = 6;   
  6.         System.out.println(counts[0]);  
  7.     }   
  8.   
  9.     public static void main(String[] args) {   
  10.         int[] count = { 12345 };   
  11.         change(count);  
  12.         System.out.println(count[0]);  
  13.     }   
  14. }  

輸出結果是6 6 也就是引用的值改變了原來的值

引用傳遞的例子:(物件)

定義一個A物件:

  1. package com.other.test;  
  2.   
  3. public class A {  
  4.     int i = 0;  
  5. }  

對上邊物件操作的類:
  1. package com.other.test;  
  2.   
  3. public class Test {  
  4.     public static void add(A a) {   
  5.         //a = new A();   ①  
  6.         a.i++;  
  7.     }   
  8.   
  9.     public static void main(String args[]) {   
  10.         A a = new A();   
  11.         add(a);   
  12.         System.out.println(a.i );  
  13.     }   
  14. }  

當把①註解掉時,輸出的結果是1,當①沒有註解是是0,原因是 a =new A();構造了新的A物件就不是傳遞的那個物件了。

看看String的情況:

  1. package com.other.test;  
  2.   
  3. public class Test {  
  4.     String str = new String("old");   
  5.     char[] ch = { 'a''b''c' };   
  6.     public static void main(String args[]) {   
  7.         Test ex = new Test();   
  8.         ex.change(ex.str, ex.ch);   
  9.         System.out.print(ex.str + " and ");   
  10.         System.out.println(ex.ch);  
  11.     }   
  12.   
  13.     public void change(String str, char ch[]) {   
  14.         str = "new";   
  15.         ch[0] = 'd';  
  16.     }  
  17. }  

輸出的結果的是 old and dbc也就是傳遞String並不會改變原值,而是建立了一個新值。 ch[]就是一個簡單的陣列的傳遞。

( 物件包括物件引用即地址和物件的內容)

String 比較特別,看過String 程式碼的都知道, String 是 final的。所以值是不變的。 函式中String物件引用的副本指向了另外一個新String物件,而陣列物件引用的副本沒有改變,而是改變物件中資料的內容. 
  對於物件型別,也就是Object的子類,如果你在方法中修改了它的成員的值,那個修改是生效的,方法呼叫結束後,它的成員是新的值,但是如果你把它指向一個其它的物件,方法呼叫結束後,原來對它的引用並沒用指向新的物件。 
  Java引數,不管是原始型別還是引用型別,傳遞的都是副本(有另外一種說法是傳值,但是說傳副本更好理解吧,傳值通常是相對傳址而言)。 
  如果引數型別是原始型別,那麼傳過來的就是這個引數的一個副本,也就是這個原始引數的值,這個跟之前所談的傳值是一樣的。如果在函式中改變了副本的值不會改變原始的值.
  如果引數型別是引用型別,那麼傳過來的就是這個引用引數的副本,這個副本存放的是引數的地址。如果在函式中沒有改變這個副本的地址,而是改變了地址中的值,那麼在函式內的改變會影響到傳入的引數。如果在函式中改變了副本的地址,如new一個,那麼副本就指向了一個新的地址,此時傳入的引數還是指向原來的地址,所以不會改變引數的值

相關文章