亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? 破除java神話之二:參數是傳址的 .txt

?? Java技巧與編程經驗談共32個文件
?? TXT
字號:
 破除java神話之二:參數是傳址的 
 作者:Cherami <BR>
email:<A HREF="mailto:cherami@javaresearch.org">cherami@javaresearch.org</A><BR>
<HR>
在不同的java新聞組中,參數是傳值還是傳址一直是一個經常被爭辯的話題。誤解的中心是以下兩個事實:<BR>
1、對象是傳引用的<BR>
2、參數是傳值的<BR>
這兩個能夠同時成立嗎?一個字:是!在java中,你從來沒有傳遞對象,你傳遞的僅僅是對象的引用!一句話,java是傳引用的。然而,當你傳遞一個參數,那么只有一種參數傳遞機制:傳值!<BR>

通常,當程序員討論傳值和傳引用時,他們是指語言的參數傳遞機制,c++同時支持這兩種機制,因此,以前使用過c++的程序員開始好像不能確定的java是如何傳參數的。java語言為了事情變得簡單只支持參數傳值的機制。<BR>
java中的變量有兩種類型:引用類型和原始類型。當他們被作為參數傳遞給方法時,他們都是傳值的。這是一個非常重要的差別,下面的代碼范例將說明這一點。<BR>
在繼續前,我們有必要定義一下傳值和傳引用。傳值意味著當參數被傳遞給一個方法或者函數時,方法或者函數接收到的是原始值的副本。因此,如果方法或者函數修改了參數,受影響的只是副本,原始值保持不變。<BR>
關于java中的參數傳遞的混亂是因為很多java程序員是從c++轉變過來的。c++有引用和非引用類型的變量,并且分別是通過傳引用和傳值得。java語言有原始類型和對象引用,那么,按照邏輯,java對于原始類型使用傳值而對引用是傳引用的,就像c++一樣。畢竟,你會想到如果你正在傳遞一個引用,那么它一定是傳引用的。這是一個很誘惑人的想法,但是是錯誤的!<BR>
在c++和java中,當函數的參數不是引用時,你傳遞的是值得副本(傳值)。但是對于引用類型就不同了。在c++中,當參數是引用類型,你傳遞的是引用或者內存地址(傳引用),而在java中,傳遞一個引用類型的參數的結果只是傳遞引用的副本(傳值)而非引用自身。這是一個非常重要的區別!java不考慮參數的類型,一律傳遞參數的副本。<BR>
仍然不信?如果java中是傳引用,那么下面的范例中的swap方法將交換他們的參數。因為是傳值,因此這個方法不是像期望的那樣正常工作。<BR>
<pre>
class Swap
{
public static void main(String args[]) 
{ 
Integer a, b; 
int i,j;
a = new Integer(10);
b = new Integer(50); 
i = 5;
j = 9; 
System.out.println("Before Swap, a is " + a); 
System.out.println("Before Swap, b is " + b); 
swap(a, b); 
System.out.println("After Swap a is " + a); 
System.out.println("After Swap b is " + b); 
System.out.println("Before Swap i is " + i); 
System.out.println("Before Swap j is " + j); 
swap(i,j); 
System.out.println("After Swap i is " + i);
System.out.println("After Swap j is " + j); 
}
public static void swap(Integer ia, Integer ib)
{
Integer temp = ia; 
ia = ib; 
ib = temp; 
}
public static void swap(int li, int lj) 
{ 
int temp = li; 
li = lj; 
lj = temp; 
} 
} 
</pre>

上面程序的輸出是: <BR>
<PRE>
Before Swap, a is 10 
Before Swap, b is 50
After Swap a is 10 
After Swap b is 50 
Before Swap i is 5 
Before Swap j is 9 
After Swap i is 5 
After Swap j is 9 
</PRE>
因為swap方法接收到的是引用參數的副本(傳值),對他們的修改不會反射到調用代碼。<BR>

譯者注:在傳遞引用和原始類型時還是有不同的,考慮以下的代碼:
<pre>
class Change
{
public static void main(String args[]) 
{ 
StringBuffer a=new StringBuffer("ok"); 
int i;
i = 5;
System.out.println("Before change, a is " + a); 
change(a); 
System.out.println("After change a is " + a); 
System.out.println("Before change i is " + i); 
change(i); 
System.out.println("After change i is " + i);
}
public static void change(StringBuffer ia)
{
ia.append(" ok?");
}
public static void change(int li) 
{ 
li = 10; 
} 
}
</pre>
程序的輸出為:<BR>
<PRE>
Before change, a is ok
After change a is ok ok?
Before change i is 5
After change i is 5
</PRE>
,即如果傳遞的是引用,那么可以修改引用對象的內容,這個改變會影響到原來的對象,而傳遞的如果是原始類型則不會有影響。這個也是造成誤解的原因之一吧
 //example 1
#include <iostream.h>
void exch(int *p1,int *p2);

int main()
{ 
int i =1,j=2;
cout<<"i="<<i<<",j="<<j<<endl;
exch(&i,&j);
cout<<"i="<<i<<",j<"<<j<<endl;
return 0;
}

void exch(int *p1,int *p2)
{
int* temp;
temp = p1;
p1 = p2;
p2 = temp;
}
//end example 1

結果會是:
i=1,j=2
i=1,j=2

同樣不會發生任何變化,正確的寫法應該是

//example 2
#include <iostream.h>
void exch(int *p1,int *p2);

int main()
{ 
int i =1,j=2;
cout<<"i="<<i<<",j="<<j<<endl;
exch(&i,&j);
cout<<"i="<<i<<",j<"<<j<<endl;
return 0;
}

void exch(int *p1,int *p2)
{int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;}
//end example 2
結果會是:
i=1,j=2
i=2,j=1
如上面代碼說明的一樣,其實無論何種語言傳址方法都是一樣的。傳值和傳址都是把內容復制給形參。只是傳值復制得是變量的具體的值,而傳址復制的是存放給變量的地址。你只是改變了形參里的地址,變量當然沒有變化,你只有改變該地址里的值,才可以改變該變量的值。
C++里如果要改變兩個地址,應該傳的是個指向指針的指針。如下面的代碼:
//example 2
#include <iostream.h>
void exch(int **p1,int **p2);
int main()
{ int a =1,b = 2;
int *i = &a;
int *j = &b;
cout<<"a="<<a<<",b="<<b<<endl;
cout<<"*i="<<*i<<",*j="<<*j<<endl;
exch(&i,&j);
cout<<"a="<<a<<",b="<<b<<endl;
cout<<"*i="<<*i<<",*j=<"<<*j<<endl;
return 0}
void exch(int **p1,int **p2)
{int* temp;
temp = *p1;
*p1 = *p2;
*p2 = *temp;}
//end example 2
結果會是:
a=1,b=2
*i=1,*j=2
a=1,b=2
*i=2,*j=1
而Java中可以用這樣的例子:
public class Test 
{
public static void swap(Integer[] a)
{Integer temp= a[0];
a[0] = a[1];
a[1] = temp;}
public static void main(String[] args) 
{Integer[] one = new Integer[2];
one[0] = new Integer(17);
one[1] = new Integer(3);
System.out.println("before swap");
System.out.println("one[0] is"+one[0]);
System.out.println("one[1] is"+one[1]);
swap(one);
System.out.println("after swap");
System.out.println("one[0] is"+one[0]);
System.out.println("one[1] is"+one[1]);}
}
結果是:
before swap
one[0] is 17
one[1] is 3
after swap
one[0] is 3
one[1] is 17
上面只是我個人的理解,不知道有沒有錯誤,請大家批評指點。
 c++里哪里有那么麻煩?
直接用&進行引用就行了
#include <iostream.h>
int swap(int& i,int& j);
void main()
{int i=1,j=2;
cout<<"i= "<<i<<" j= "<<j<<endl;
swap(i,j);
cout<<"i= "<<i<<" j= "<<j<<endl;}
int swap(int& i,int& j)
{int temp;
temp=i;
i=j;
j=temp;}  
 你的理解是錯誤的,java的參數是傳址的,如果是傳值的那么每一個對象應該實現clone方法
不然如何傳遞對象的拷貝,你舉的例子正好使用的是不變類,如果你使用一個大的對象結果肯定不同的  什么是值傳遞?就是把變量復制一份吧?基本類型作為參數傳遞的時候,復制了一份,于是叫做值傳遞;傳對象(的引用)的時候,也把它(對象的引用)復制了一份,只不過復制的是引用本身,因為Java里面所謂的對象都是指“對象的引用”,所以這也是“值傳遞”。
但是如果你以C/C++的觀點來看,無疑會認為Java混淆了按引用傳遞的概念。  
 jackypeng:你的理解是錯誤的。因為Java的單根繼承,所有對象都實現了clone方法。
如果希望傳遞對象的拷貝,應該顯式調用clone方法。(是否需要override Object.clone(),那是出于“深”、“淺”的考慮)。不知道你所說的不變類是指哪個,Integer?  
 實際上一句話就說清楚了,為什么要寫這么多來混淆概念呢?
Java中,一切對象作為參數時都是傳引用,一切原始類型(int,float,...)都是傳值。   
 I don't know how to type Simplified Chinese, so pardon me for using English.
I just want to state one point.
There are only 2 modes in parameter passing in Java functions.
One is for primitives, that is <<pass by value>> i.e. <<pass by copying>>.
The other is for Objects, that is <<pass reference by value>> i.e. java will copy the reference of an object and pass it to the function.
And that is why you can *never* write a swap function in Java as you can in C or C++. The common workaround to do swapping (as used extensive in JDK) is to put the object you want to swap in an array, and change the index of the array in the swap function.

public static void main(String[] args){
String a="aa", b="bb";
String[] data=new String[2];
data[0]=a;
data[1]=b;
swap(data);
a=data[0];
b=data[1];
//now a="bb"; and b="aa"
}
public static void swap(String[] data){
String temp;
temp=data[0];
data[0]=data[1];
data[1]=temp;
}

Please notice the subtle difference between C++'s pass by reference and Java's pass reference by value.
Hope this help.  
 I don't know how to type Simplified Chinese, so pardon me for using English.
I just want to state one point.
There are only 2 modes in parameter passing in Java functions.
One is for primitives, that is <<pass by value>> i.e. <<pass by copying>>.
The other is for Objects, that is <<pass reference by value>> i.e. java will copy the reference of an object and pass it to the function.
And that is why you can *never* write a swap function in Java as you can in C or C++. The common workaround to do swapping (as used extensive in JDK) is to put the object you want to swap in an array, and change the index of the array in the swap function.

public static void main(String[] args){
String a="aa", b="bb";
String[] data=new String[2];
data[0]=a;
data[1]=b;
swap(data);
a=data[0];
b=data[1];
//now a="bb"; and b="aa"
}
public static void swap(String[] data){
String temp;
temp=data[0];
data[0]=data[1];
data[1]=temp;
}

Please notice the subtle difference between C++'s pass by reference and Java's pass reference by value.
Hope this help.  
 class Change
{
public static void main(String args[]) 
{ 
String a=new String("ok"); 

System.out.println("Before change, a is " + a); 
change(a); 
System.out.println("After change a is " + a); 

}
public static void change(String ia)
{
ia.concat("?");
}
}

可是輸出的a沒有任何變化,這就使我有點不懂了——不是說對象是傳引用的嗎,為什么您的例子成功了,但我卻沒有?我想這可能是兩個方法的不同吧.這并不能推翻Cherami先生的說法.
java對象還是傳引用的.  
 class Change
{
public static void main(String args[]) 
{ 
String a=new String("ok");
StringBuffer b=new StringBuffer("qi"); 


System.out.println("Before change, a is " + a); 
System.out.println("Before change, b is " + b); 
changea(a); 
changeb(b);
System.out.println("After change, a is " + a); 
System.out.println("After change, b is " + b); 

}
public static void changea(String ia)
{
if(ia.concat("?").equals(ia))System.out.println("ia ok");

}
public static void changeb(StringBuffer ib)
{
if(ib.append("?").equals(ib))System.out.println("ib ok");
}
}
 
請看看我的專欄里面的另外兩篇文章:
我對《Java 應用程序中的按值傳遞語義》的理解 
Java 應用程序中的按值傳遞語義
以上兩篇文章都在J2SE文章區。  
 sun2bin 說的沒錯在java 中基本類型直接采用值傳遞,就是把值復制一份,而對于任何其它復合類型傳遞的是對象的reference,相當于對象的地址。
函數調用時,每個函數都有它自己的參數區,對于基本類型直接把數據復制到參數區,而對于復合類型是把對象的reference復制到參數區。
看下面簡單例子:
/**
*Test for parameter transfer
*
**/
public class PassParameter
{

/**
*Change the value of the arrary
*@para int data[], the Object of a int arrary
*
**/
public PassParameter(int data[])
{
int temp = data[1];
data[1] = data[0];
data[0] = temp;
}

public static void main(String[] args)
{
int[] temp = new int[2];
temp[0] = 0;
temp[1] = 1;
PassParameter passParameter1 = new PassParameter(temp);
System.out.print(temp[0]+" "+temp[1]);
}
}

我們可以發現外部對象temp 在經過PassParameter的初始化方法處理后,值就發生了變化,輸出的將是:1 0
實際上C 與java 在參數的值或地址的傳遞問題上仔細想想,就會發現他們沒有本質的區別,c中的簡單類型也是值傳遞,復合類型傳遞的是存放指向對象或實體的地址的變量(該變量(地址)存放的是對象的地址),對于指針實際上是直接將對象的地址值直接復制到函數的參數區。
c與java的不同在于c中存在存放地址的變量(指針),這樣就可以通過指針運算隨意訪問未定義的空間。java中不存在這樣的存放地址的變量(指針),程序中的每個對象名稱實際上都記錄在一個變量表中,每個變量名對應一個reference No. 函數調用時傳遞的就是這個reference No。(系統再根據這個reference no 找到相關對象的地址(我的推測,系統中記錄了每個對象的地址和reference No的對應關系),也因此我們就無法使用沒定義過的對象)

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
91 com成人网| 欧美性感一类影片在线播放| 成人教育av在线| 色国产综合视频| 久久综合久久久久88| 一区二区三区在线视频免费| 久久草av在线| 欧美图区在线视频| 欧美国产禁国产网站cc| 日韩精品久久理论片| 99精品视频在线免费观看| 欧美mv和日韩mv国产网站| 亚洲精品乱码久久久久久久久 | 色婷婷国产精品综合在线观看| 日韩你懂的电影在线观看| 亚洲精品午夜久久久| 蜜臀av性久久久久av蜜臀妖精| 色婷婷一区二区| 国产精品久久毛片a| 日韩中文字幕区一区有砖一区| 91日韩一区二区三区| 欧美唯美清纯偷拍| 亚洲综合一区在线| 91在线视频免费观看| 中文字幕巨乱亚洲| 国产suv一区二区三区88区| 欧美一区二区三区男人的天堂| 亚洲日本va午夜在线影院| 成人污视频在线观看| 精品欧美一区二区三区精品久久| 亚洲成av人片观看| 95精品视频在线| 中文字幕中文字幕一区二区| 国产一区二区三区观看| 欧美xxxx老人做受| 老鸭窝一区二区久久精品| 欧美一级日韩一级| 午夜久久久久久久久久一区二区| 色综合咪咪久久| 一区二区三区成人| 色999日韩国产欧美一区二区| 欧美国产日韩一二三区| 国产成人精品网址| 国产精品理论片在线观看| heyzo一本久久综合| 国产精品久99| av网站一区二区三区| 亚洲人成精品久久久久久| 色狠狠av一区二区三区| 亚洲欧美日韩中文字幕一区二区三区 | 亚洲国产精品久久久久婷婷884 | 亚洲福利视频一区| 91麻豆精品国产自产在线观看一区| 午夜电影久久久| 在线不卡的av| 日本不卡免费在线视频| 日韩欧美激情四射| 成人一区二区在线观看| 国产三级一区二区三区| 懂色av一区二区三区免费观看| 日本一区二区免费在线| 色呦呦一区二区三区| 日韩激情av在线| 久久精品人人做| 91麻豆123| 日韩精品久久理论片| 亚洲国产精品v| 日本高清不卡视频| 捆绑调教一区二区三区| 日本一区二区三区在线观看| 欧美视频你懂的| 国产精品一区二区你懂的| 中文字幕一区二区5566日韩| 欧美精品日韩精品| 成人午夜精品在线| 婷婷成人综合网| 国产精品进线69影院| 日韩欧美一区二区免费| av成人免费在线观看| 三级一区在线视频先锋| 国产精品网站一区| 欧美一区二区三区在线电影| 成人性生交大片免费看中文网站| 亚洲成人av中文| 国产精品人妖ts系列视频| 538在线一区二区精品国产| 成人小视频在线| 麻豆精品在线播放| 亚洲综合视频在线观看| 国产欧美精品一区二区三区四区| 欧美日韩电影一区| av在线不卡网| 国产精品一级片在线观看| 奇米色一区二区三区四区| 一区二区理论电影在线观看| 国产色一区二区| 久久美女艺术照精彩视频福利播放| 在线电影一区二区三区| 色婷婷综合久久久久中文一区二区 | 91在线视频播放| 国产乱妇无码大片在线观看| 日日噜噜夜夜狠狠视频欧美人 | 国产午夜精品久久久久久久| 制服丝袜日韩国产| 欧美日韩精品系列| 色成年激情久久综合| av电影在线观看不卡| 国产91丝袜在线观看| 国产成人免费xxxxxxxx| 日本最新不卡在线| 亚洲国产精品久久人人爱| 中文字幕一区二区三中文字幕| 久久精品视频在线免费观看| 精品久久人人做人人爱| 欧美精品一区二区三区很污很色的| 69成人精品免费视频| 69p69国产精品| 日韩视频免费观看高清完整版 | 一区二区三区鲁丝不卡| 综合久久久久久久| 1000部国产精品成人观看| 国产精品久久久久久久久免费桃花 | 日韩理论片在线| 1区2区3区精品视频| 亚洲精选一二三| 一区二区三区91| 亚洲bt欧美bt精品| 日产国产欧美视频一区精品| 蜜臀久久久久久久| 极品美女销魂一区二区三区| 极品瑜伽女神91| 高清视频一区二区| 99久久99久久精品免费看蜜桃| 色综合色狠狠天天综合色| 欧美性猛交xxxxxxxx| 欧美日本不卡视频| 精品日韩欧美在线| 国产欧美日韩精品一区| 亚洲欧美在线视频观看| 亚洲综合一二区| 久久国产精品99精品国产| 国产一区二区h| 成人黄色免费短视频| 在线观看一区二区精品视频| 欧美一区二区日韩一区二区| 欧美tickling挠脚心丨vk| 日本一区二区在线不卡| 亚洲在线观看免费视频| 麻豆freexxxx性91精品| 成人免费毛片嘿嘿连载视频| 91国偷自产一区二区使用方法| 欧美一区二区在线免费播放| 久久久久久久久一| 亚洲午夜成aⅴ人片| 国模大尺度一区二区三区| 91在线观看视频| 制服.丝袜.亚洲.中文.综合| 欧美国产日产图区| 日韩中文字幕麻豆| 粉嫩13p一区二区三区| 欧美丰满嫩嫩电影| 欧美激情综合网| 午夜av区久久| 99久久国产免费看| 欧美xxx久久| 亚洲成人在线观看视频| 大胆亚洲人体视频| 欧美xxxxxxxx| 亚洲va韩国va欧美va精品| 成人小视频免费在线观看| 日韩一级二级三级| 有码一区二区三区| 懂色av一区二区三区蜜臀| 日韩女优视频免费观看| 亚洲免费看黄网站| 国产米奇在线777精品观看| 欧美精品一二三| 亚洲天堂中文字幕| 国产精品18久久久久久久久| 欧美一级生活片| 亚洲国产综合91精品麻豆| 91视频com| 国产精品你懂的在线| 激情都市一区二区| 69堂国产成人免费视频| 一区二区不卡在线播放 | 精品久久久久久久久久久久久久久 | av网站免费线看精品| 国产日韩欧美精品电影三级在线| 日产欧产美韩系列久久99| 欧美日韩国产免费一区二区| 亚洲综合一二三区| 在线观看视频91| 亚洲免费av观看| 色婷婷国产精品| 亚洲欧美一区二区三区久本道91 | 国内精品国产成人国产三级粉色| 欧美精品乱码久久久久久按摩| 亚洲国产日韩一区二区| 在线观看视频一区二区欧美日韩|