熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

Java 應用程序中的按值傳遞語義

2013-11-15 11:48:04  來源: JSP教程 

  幾個月前developerWorks 發布了我的書 Practical Java 中的一些節選該書是由 AddisonWesley 出版的首先我將利用 developerWorks 上的此欄目回答讀者提出的一些問題然後對有關這些節選的各種評論作一答復
  
  
  
  節選理解參數是按值而不是按引用傳遞的說明 Java 應用程序有且僅有的一種參數傳遞機制即按值傳遞寫它是為了揭穿普遍存在的一種神話即認為 Java 應用程序按引用傳遞參數以避免因依賴按引用傳遞這一行為而導致的常見編程錯誤
  
  
  
  對此節選的某些反饋意見認為我把這一問題搞糊塗了或者將它完全搞錯了許多不同意我的讀者用 C++ 語言作為例子因此在此欄目中我將使用 C++ 和 Java 應用程序進一步闡明一些事實
  
  
  
  要點
  
  讀完所有的評論以後問題終於明白了至少在一個主要問題上產生了混淆某些評論認為我的節選是錯的因為對象是按引用傳遞的對象確實是按引用傳遞的節選與這沒有沖突節選中說所有參數都是按值 另一個參數 傳遞的下面的說法是正確的在 Java 應用程序中永遠不會傳遞對象而只傳遞對象引用因此是按引用傳遞對象但重要的是要區分參數是如何傳遞的這才是該節選的意圖Java 應用程序按引用傳遞對象這一事實並不意味著 Java 應用程序按引用傳遞參數參數可以是對象引用而 Java 應用程序是按值傳遞對象引用的
  
  
  
  C++ 和 Java 應用程序中的參數傳遞
  
  Java 應用程序中的變量可以為以下兩種類型之一引用類型或基本類型當作為參數傳遞給一個方法時處理這兩種類型的方式是相同的兩種類型都是按值傳遞的沒有一種按引用傳遞這是一個重要特性正如隨後的代碼示例所示的那樣
  
  
  
  在繼續討論之前定義按值傳遞和按引用傳遞這兩個術語是重要的按值傳遞意味著當將一個參數傳遞給一個函數時函數接收的是原始值的一個副本因此如果函數修改了該參數僅改變副本而原始值保持不變按引用傳遞意味著當將一個參數傳遞給一個函數時函數接收的是原始值的內存地址而不是值的副本因此如果函數修改了該參數調用代碼中的原始值也隨之改變
  
  
  
  關於 Java 應用程序中參數傳遞的某些混淆源於這樣一個事實許多程序員都是從 C++ 編程轉向 Java 編程的C++ 既包含非引用類型又包含引用類型並分別按值和按引用傳遞它們Java 編程語言有基本類型和對象引用因此認為 Java 應用程序像 C++ 那樣對基本類型使用按值傳遞而對引用使用按引用傳遞是符合邏輯的畢竟您會這麼想如果正在傳遞一個引用則它一定是按引用傳遞的很容易就會相信這一點實際上有一段時間我也相信是這樣但這不正確
  
  
  
  在 C++ 和 Java 應用程序中當傳遞給函數的參數不是引用時傳遞的都是該值的一個副本(按值傳遞)區別在於引用在 C++ 中當傳遞給函數的參數是引用時您傳遞的就是這個引用或者內存地址(按引用傳遞)在 Java 應用程序中當對象引用是傳遞給方法的一個參數時您傳遞的是該引用的一個副本(按值傳遞)而不是引用本身請注意調用方法的對象引用和副本都指向同一個對象這是一個重要區別Java 應用程序在傳遞不同類型的參數時其作法與 C++ 並無不同Java 應用程序按值傳遞所有參數這樣就制作所有參數的副本而不管它們的類型
  
  
  
  示例
  
  我們將使用前面的定義和討論分析一些示例首先考慮一段 C++ 代碼C++ 語言同時使用按值傳遞和按引用傳遞的參數傳遞機制
  
  
  
  清單 C++ 示例 #include
  
  #include
  
  
  
  void modify(int a int *P int &r);
  
  
  
  int main (int argc char** argv)
  
  {
  
  int val ref;
  
  int *pint;
  
  
  
  val = ;
  
  ref = ;
  
  pint = (int*)malloc(sizeof(int));
  
  *pint = ;
  
  
  
  printf(val is %d\n val);
  
  printf(pint is %d\n pint);
  
  printf(*pint is %d\n *pint);
  
  printf(ref is %d\n\n ref);
  
  
  
  printf(calling modify\n);
  
  //按值傳遞 val 和 pint按引用傳遞 ref
  
  modify(val pint ref);
  
  printf(returned from modify\n\n);
  
  
  
  printf(val is %d\n val);
  
  printf(pint is %d\n pint);
  
  printf(*pint is %d\n *pint);
  
  printf(ref is %d\n ref);
  
  
  
  return ;
  
  }
  
  
  
  void modify(int a int *p int &r)
  
  {
  
  printf(in modify\n);
  
  a = ;
  
  *p = ;
  
  p = ;
  
  r = ;
  
  printf(a is %d\n a);
  
  printf(p is %d\n p);
  
  printf(r is %d\n r);
  
  }
  
  
  
  
  
  
  
  
  
  這段代碼的輸出為
  
  
  
  清單 C++ 代碼的輸出 val is
  
  pint is
  
  *pint is
  
  ref is
  
  
  
  calling modify
  
  in modify
  
  a is
  
  p is
  
  r is
  
  returned from modify
  
  
  
  val is
  
  pint is
  
  *pint is
  
  ref is
  
  
  
  
  
  
  
  這段代碼聲明了三個變量兩個整型變量和一個指針變量設置了每個變量的初始值並將其打印出來同時打印出了指針值及其所指向的值然後將所有三個變量作為參數傳遞給 modify 函數前兩個參數是按值傳遞的最後一個參數是按引用傳遞的modify 函數的函數原型表明最後一個參數要作為引用傳遞回想一下C++ 按值傳遞所有參數引用除外後者是按引用傳遞的
  
  
  
  modify 函數更改了所有三個參數的值
  
  
  
  將第一個參數設置為
  
  將第二個參數所指向的值設置為 然後將第二個參數設置為
  
  將第三個參數設置為
  
  
  
  將新值打印出來然後函數返回當執行返回到 main 時再次打印出這三個參數的值以及指針所指向的值作為第一個和第二個參數傳遞的變量不受 modify 函數的影響因為它們是按值傳遞的但指針所指向的值改變了請注意與前兩個參數不同作為最後一個參數傳遞的變量被 modify 函數改變了因為它是按引用傳遞的
  
  
  
  現在考慮用 Java 語言編寫的類似代碼
  
  
  
  清單 Java 應用程序 class Test
  
  {
  
  public static void main(String args[])
  
  {
  
  int val;
  
  StringBuffer sb sb;
  
  
  
  val = ;
  
  sb = new StringBuffer(apples);
  
  sb = new StringBuffer(pears);
  
  Systemoutprintln(val is + val);
  
  Systemoutprintln(sb is + sb);
  
  Systemoutprintln(sb is + sb);
  
  Systemoutprintln();
  
  
  
  Systemoutprintln(calling modify);
  
  //按值傳遞所有參數
  
  modify(val sb sb);
  
  Systemoutprintln(returned from modify);
  
  Systemoutprintln();
  
  
  
  Systemoutprintln(val is + val);
  
  Systemoutprintln(sb is + sb);
  
  Systemoutprintln(sb is + sb);
  
  }
  
  
  
  public static void modify(int a StringBuffer r
  
  StringBuffer r)
  
  {
  
  Systemoutprintln(in modify);
  
  a = ;
  
  r = null; //
  
  rappend( taste good);
  
  Systemoutprintln(a is + a);
  
  Systemoutprintln(r is + r);
  
  Systemoutprintln(r is + r);
  
  }
  
  }
  
  
  
  
  
  
  
  這段代碼的輸出為
  
  
  
  清單 Java 應用程序的輸出 val is
  
  sb is apples
  
  sb is pears
  
  
  
  calling modify
  
  in modify
  
  a is
  
  r is null
  
  r is pears taste good
  
  returned from modify
  
  
  
  val is
  
  sb is apples
  
  sb is pears taste good

From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19648.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.