歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java 方法傳參方式: 按值調用

程序設計語言中將參數傳遞給方法的幾種方式:

  1. 按名調用(call by name): Algol 語言采用此方式, 已成為歷史;
  2. 按值調用(call by value): 方法接收到的是調用者提供的 變量值;
  3. 按引用調用(call by reference): 方法接受到的是調用者低筒的 變量地址;

C++ 支持 按值調用按引用調用:

void func(int arg); // 按值調用;
void func(int& arg); // 按引用調用;

而 Java 只支持 按值調用, 也就是說方法得到的是所有參數值的一個拷貝, 在方法內對參數值進行修改是不會影響原值的.

然而方法參數有兩種類型:

  1. 基本數據類型: 數字, 布爾值;
  2. 對象引用.

當方法參數是 對象引用 時, 在方法很容易的調用其 setXXX 方法修改該對象屬性值, 在退出方法後該修改仍然有效, 但這仍舊只是 按值調用.
因為參數是 對象引用, 在該方法內仍舊執行原對象(類似 C++ 的指針), 調用它的 setXXX 方法當然能修改對象屬性了. 但也僅限於修改對象屬性(狀態), 而不能通過 new 等方式對原對象進行修改.

如果還有疑問, 就請看看這個例子:

class MyObject {
  private String name;
  MyObject(String name) {
    this.name = name;
  }
}

staticvoidswap(MyObject first, MyObject second) {
  MyObject temp = first;
  first = second;
  second = first;
}

staticvoidtestSwap() {
  MyObject a = new MyObject("a");
  MyObject b = new MyObject("b");

  swap(a, b);
}

請問在執行 swap() 函數後, 對象 a 和 對象 b 的 name 是否變化?

答案是沒有變化. 在 testSwap() 方法中, firstsecond 完成交換並分別指向對方. 但是, 在進入方法時, 它們拿到的是對象引用的拷貝(位置), 類似於:

  • 進入 swap() 方法前, a 知道在內存地址為 100 的地方存儲了一個 MyObject 對象, 'b' 知道在內存地址為 200 的地方存儲了另一個 MyObject 對象;
  • 進入 swap() 方法時, a 將它的對象引用復制一份給 first, 也就是說 first 知道內存地址為 100 的地方有一個 MyObject 對象. second 同理;
  • 在退出 swap() 方法時, firstsecond 交換值, 也就是說 first 知道內存地址為 200 的地方有一個 MyObject 對象, 它已經跟內存地址為 100 的 MyObject 對象沒有任何關系了. second 同理;
  • 在退出 swap() 方法後, firstsecond 被銷毀, a 仍舊是知道內存地址為 100 的地方有一個 MyObject 對象...

其實, 這就是 C/C++ 的指針.

順便說一句, 通過 C++ 的 按引用調用 可以很方便實現 swap() 函數. 當然, 用指針也是支持滴, 只不過稍微復雜點(這裡只給出聲明, 有興趣的同學自己去寫實現吧):

MyObject* a = new MyObject("a");
MyObject* b = new MyObject("b");


void swap(MyObject& first, MyObject& second); // C++ 引用

void swap(MyObject **first, MyObject **second); // C/C++ 指針版 swap

綜上, java 中的方法參數:

  • 不能修改一個基本數據類型的參數(即數值型或布爾型);
  • 可以改變一個對象參數的狀態;
  • 不能讓對象參數引用一個新的對象.

Copyright © Linux教程網 All Rights Reserved