2010年10月26日 星期二

[Java] Refenerce type vs Primitive type

 習慣C的人,想改變參數內容時大多會用pointer
(利用改變pointer所指的內容來達成 call by reference 的效果)
 
但Java語言沒有指標(pointer),只有reference type
它處理參數是採用什麼方式呢?
 
我們可以將變數型態歸類為兩種
1.primitive type:
boolean    char      byte     short      int    long    float     double
 
2.reference type(利用class定義的型態都是這種type)
---------------------------------------------------------------------
<1>我們先討論primitive type:
primitive type的參數傳遞,會分配新的記憶體空間給function使用,
它將傳入的值拷貝一份到新的記憶體空間,才開始給function做處理,
因此返回的時候不會影響原來變數的值。
 
//like this:
public void function(int pInt)
{
  pInt=pInt+20;
}
//主程式:
int aInt=100;
function(aInt); // 呼叫function傳入aInt這個primitive type變數
System.out.println(aInt);
//這一行會印出 100,不是120!!
//因為將pInt加20的指令,是改變一個新分配的記憶體空間,
//這個新分配的空間在function return時就不見了(成了沒有指標的垃圾)
 
<2>第二種情況,參數是reference type
例如: Integer,StringBuffer , or 自定形態...
如果傳進去,在裡面改變其值,那返回時其值會真的改變!!!
 
class MyType
{  public int Val;
}
public void function(MyType  pMyType)
{ pMyType.Val = pMyType.Val +20;
}
//主程式:
MyType aMyType;
aMyType.Val=100;
function(aMyType); // 呼叫function想改變aMyType裡面的myTypeVal值
System.out.println(aMyType.Val);
//這裡會印出120!!! 它...真的變大了.......
---------------------------------------------------------------------
******* 陷阱 ********
第三種情況(其實也是reference type),參數是 String 型態
將String傳進去,如果改變它的值,會怎樣呢??
照上面的講,它是reference type,應該在返回之後,
它的值就會被改變才對!
我們來看看是不是這樣:
 
void function(String pString)
{
  pString="New String";
}
//主程式:
String aString="Initial String";
function(aString);
System.out.println(aString);
 
//嗯!這一行會印出什麼?
//答案是 Initial String
//   ...... Why?? ......
//為什麼跟我們預料的不一樣呢?
 
//因為雖然它是reference type
//可是將pString重新設定的那個指令: pString="New String";
//會幫 pString 分派一個新的記憶體空間,
//此新的記憶體空間不會跟原來的重疊!
//所以返回的時候,原本的記憶體空間並沒有被改變!
//!!!!!這是String特別要注意的地方 !!!!!
//
//Java語言對String設定的定義:
//pString="New String"; 這行指令等於: pString=new String("New String");
//所以它才會分配一個新的記憶體空間 
 
搞懂了Java對於參數的處理,
我們在處理變數時才不會出錯,
除了String型態的設定要特別注意以外,
其他改變reference type參數的動作,
都會直接影響原來變數的內含值!
From Google

沒有留言:

張貼留言