青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

woaidongmao

文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
數據加載中……

語言深入:java中究竟是傳值還是傳引用

首先,推薦對Java有一定理解的同仁一本書《Practical Java》。在《Practical Java》中也有一個章節介紹Java中關于傳值和傳引用的問題,堪稱經典。

Practical Java

Java中,事實上底層工作原理不存在傳引用的概念,這也象《Practical Java》中所說的那樣,Java中只有傳值。這句話理解起來需要費一定的周折。

熟悉C程序員都用過指針,對指針可謂愛之深恨之切。指針是指向一塊內存地址的內存數據(有些拗口),也就是說指針本身是一個占用4字節內存的int32 系統內),而這個int值恰恰又是另一塊內存的地址。比如"hello"這個字串,存放在@0x0000F000這個地址到@0x0000F005這段內存區域內(包括0x00的結束字節)。而在@0x0000FFF0@0x0000FFF03這四個字節內存放著一個int,這個int的值是 @0x0000F000。這樣就形成了一個指向"hello"字串的指針。

Java中,很多人說沒有指針,事實上,在Java更深層次里,到處都是大師封裝好的精美絕倫的指針。為了更容易的講解Java中關于類和類型的調用,Java中出現了值與引用的說法。淺顯的來說,我們可以認為 Java中的引用與C中的指針等效(其實差別非常非常大,但是為了說明我們今天的問題,把他們理解為等效是沒有任何問題的)。

所謂傳引用的說法是為了更好的講解調用方式。基于上面對指針的理解,我們不難看出,指針其實也是一個int值,所謂傳引用,我們是復制了復制了指針的int值進行傳遞。為了便于理解,我們可以姑且把指針看作一種數據類型,透明化指針的int特性,從而提出傳引用的概念。

重申一遍:Java中只有傳值。

1
所謂傳值和傳引用

傳值和傳引用的問題一直是Java里爭論的話題。與C++不同的,Java里面沒有指針的概念,Java的設計者巧妙的對指針的操作進行了管理。事實上,在懂C++Java程序員眼中,Java到處都是精美絕倫的指針。
下面舉個簡單的例子,說明什么是傳值,什么是傳引用。
//
1
void method1(){
int x=0;
this.change(x);
System.out.println(x);
}

void int change(int i){
i=1;
}

很顯然的,在mothod1中執行了change(x)后,x的值并不會因為change方法中將輸入參數賦值為1而變成1,也就是說在執行change(x)后,x的值z依然是0。這是因為x傳遞給change(int i)的是值。這就是最簡單的傳值。
同樣的,進行一點簡單的變化。
//
2
void method1(){
StringBuffer x=new StringBuffer("Hello");
this.change(x);
System.out.println(x);
}

void int change(StringBuffer i){
i.append(" world!");
}
看起來沒什么變化,但是這次mothed1中執行了change (x)后,x的值不再是"Hello"了,而是變成了"Hello world!"。這是因為x傳遞給change(i)的是x的引用。這是最經典的傳引用。
似乎有些奇怪了,兩段程序沒有特別的不同,可是為什么一個傳的是值而另一個傳的是引用呢?......

2
非要搞清楚傳值還是傳引用的問題嗎?

搞清楚這自然是有必要的,不然我也不需要寫這么多了,不過的確沒有到"非要"的地步。
首先,如果我們不太關心什么是傳值什么是傳引用,我們一樣能寫出漂亮的代碼,但是這些代碼在運行過程中可能會存在著極大的隱患。
全局變量是讓大家深惡痛絕(又難以割舍)的東西,原因就是使用全局變量要特別注意數據的保護。如果在多線程的程序里使用全局變量簡直就等于跟自己過不去。不了解傳值和傳引用的問題,跟使用全局變量不考慮數據保護的罪過是不相上下下的,甚至有時候比它還要糟。你會莫名其妙,為什么我的返回參數沒有起作用,為什么我傳進去的參數變成了這樣......
一個例子:
//
3
void mothed1(){
int x=0;
int y=1;
switchValue(x,y);
System.out.println("x="+x);
System.out.println("y="+y);
}
void switchValue(int a,int b){

int c=a;
a=b;
b=c;
}
上面是一個交換a,b值的函數,看起來似乎蠻正確的,但是這個函數永遠也不會完成你想要的工作。
還有一個例子:
//
4
StringBuffer a=new StringBuffer("I am a ");
StringBuffer b=a;
a.append("after append");
a=b;
System.out.println("a="+a);
在編程過程中,經常會遇到這種情況,一個變量的值要被臨時改變一下,等用完之后再恢復到開始的值。就好像上面的例子,a為了保持它的值,使用b=a做賦值,之后a被改變,再之后a把暫存在b里面的值取回來。這是我們一廂情愿的想法,而事實上,這段代碼執行后,你會發現a的值已經改變了。
以上是兩個最簡單的例子,真正的程序開發過程中,比這要復雜的情況每天都會遇到。

3
類型和類

Java
提出的思想,在Java里面任何東西都是類。但是Java里面同時還有簡單數據類型:int,byte,char,boolean,與這些數據類型相對應的類是Integer,Byte,Character,Boolean,這樣做依然不會破壞Java關于任何東西都是類的提法。
這里提到數據類型和類似乎和我們要說的傳值和傳引用的問題無關,但這是我們分辨傳值和傳引用的基礎。

4
試圖分辨傳值還是傳引用

為什么是"試圖分辨"呢?很簡單,傳值和傳引用的問題無處不在,但是似乎還沒有人能正統的給出標準,怎樣的就是值拷貝調用,怎樣的就是引用調用。面對這個問題,我們更多的應該是來自平時積累對Java的理解。
回過頭來,我們分析一下上面的幾個例子:
先看例1,即使你不明白為什么,但是你應該知道這樣做肯定不會改變x的值。為了方便說明,我們給例子都加上行號。
//
1
1 void method1(){
2   int x=0;
3   this.change(x);
4 }
5
6 void int change(int i){
7 i=7;
8}
讓我們從內存的存儲方式看一下xI之間到底是什么關系。
在執行到第2行的時候,變量x指向一個存放著int 0的內存地址。

變量x---->[存放值0]

執行第3行調用change(x)方法的時候,內存中是這樣的情形:x把自己值在內存中復制一份,然后變量i指向這個被復制出來的0。

變量x---->[存放值0]
               ↓
進行了一次值復制
變量x---->[存放值0]

這時候再執行到第7行的時候,變量i的被賦值為7,而這一步的操作已經跟x沒有任何關系了。

變量x---->[存放值0]
            
變量x---->[存放值7]

說到這里應該已經理解為什么change(x)不能改變x的值了吧?因為這個例子是傳值的。
那么,試著分析一下為什么例三中的switchValue()方法不能完成變量值交換的工作?
再看例2
//
2
1void method1(){
2 StringBuffer x=new StringBuffer("Hello");
3 this.change(x);
4}
5
6void int change(StringBuffer i){
7 i.append(" world!");
8}
2似乎和例1從代碼上看不出什么差別,但是執行結果卻是change(x)能改變x的值。依然才從內存的存儲角度來看看例2的蹊蹺在哪里。
在執行到第2行時候,同例1一樣,x指向一個存放"Hello"的內存空間。

變量x---->[存放值"Hello"]

接下來執行第三行change(x),注意,這里就與例1有了本質的不同:調用change(x)時,變量i也指向了x指向的內存空間,而不是指向x的一個拷貝。

變量x \
        -->[
存放值"Hello"]
變量x /

于是,第7行對i調用append方法,改變i指向的內存空間的值,x的值也就隨之改變了。

變量x \
        -->[
追加為"Hello World!"]
變量x /

為什么x值能改變呢?因為這個例子是傳引用的。
這幾個例子是明白了,可是很多人會開始有另一個疑問了:這樣看來,到底什么時候是傳的值什么時候是傳得引用呢?于是,我們前面講到的類型和類在這里就派上了用場:對于參數傳遞,如果是簡單數據類型,那么它傳遞的是值拷貝,對于類的實例它傳遞的是類的引用。需要注意的是,這條規則只適用于參數傳遞。為什么這么說呢?我們看看這樣一個例子:
//
5
String str="abcdefghijk";
str.replaceAll("b","B");
這兩句執行后,str的內容依然是"abcdefghijk",但是我們明明是對str操作的,為什么是這樣的呢?因為str的值究竟會不會被改變完全取決于replaceAll這個方法是怎么實現的。類似的,有這樣一個例子:
//
6
1 void method1() {
2 StringBuffer x = new StringBuffer("Hello");
3 change1(x);
4 System.out.println(x);
5 }
6
7 void method2() {
8 StringBuffer x = new StringBuffer("Hello");
9 change2(x);
10 System.out.println(x);
11 }
12
13 void change1(StringBuffer sb) {
14 sb.append(" world!");
15 }
16
17 void change2(StringBuffer sb) {
18 sb = new StringBuffer("hi");
19 sb.append(" world!");
20 }
調用method1(),屏幕打印結果為:"Hello world!"
調用method2(),我們認為結果應該是"hi world",因為sb傳進來的是引用。可是實際執行的結果是"Hello"!
難道change2()又變成傳值了?!其實change1()change2()的確都是通過參數傳入引用,但是在方法內部因為處理方法的不同而使結果大相徑庭。我們還是從內存的角度分析:
執行method1()change1()不用再多說了,上面的例子已經講解過,這里我們分析一下method2()change2()。
程序執行到第8行,x指向一個存放著"Hello"的內存空間。

變量x---->[存放值"Hello"]

9行調用change2,將sb指向x指向的內存空間,也就是傳入x的引用。

變量x \
        -->[
存放值"Hello"]
變量x /

到這里為止還沒有什么異樣,接下來執行18行,這里就出現了類似傳入值拷貝的變化:new 方法并沒有改變sb指向內存的內容,而是在內從中開辟了一塊新的空間存放串"hi",同時sb指向了這塊空間。

變量x---->[存放值"Hello"]
      ×
原有的引用被切斷
變量x---->[另一塊存放"hi"的空間]

接下來再對sb進行append已經和x沒有任何關系了。
所以,還有一條不成規則的規則:對于函數調用,最終效果是什么完全看函數內部的實現。比較標準的做法是如果會改變引用的內容,則使用void作為方法返回值,而不會改變引用內容的則在返回值中返回新的值。
雖然已經說了這么多,但是感覺傳值還是傳引用的問題依然沒有完全說清楚。因為這個問題本身就是很難歸納總結的問題,所以更多的理解要靠平時的積累和形成。下面幾個例子,給大家嘗試進行分析。
//
7,打印結果是什么?
public static void main(String[] args) {
int a;
int b;
StringBuffer c;
StringBuffer d;
a = 0;
b = a;
c = new StringBuffer("This is c");
d = c;

a = 2;
c.append("!!");

System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
System.out.println("d=" + d);
}

//
8,打印結果是什么?
public class Test{

        public static void main(String[] args) {

         StringBuffer sb = new StringBuffer("Hello ");

         System.out.println("Before change, sb = " + sb);

         changeData(sb);

         System.out.println("After changeData(n), sb = " + sb);

     }

     

        public static void changeData(StringBuffer strBuf) {

            StringBuffer sb2 = new StringBuffer("Hi ");

            strBuf = sb2;

            sb2.append("World!");

     }

}

posted on 2009-06-15 13:03 肥仔 閱讀(169) 評論(0)  編輯 收藏 引用 所屬分類: Web-后臺

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产日本欧美一区二区三区在线| 亚洲精品久久久久久一区二区| 国产精品一区在线播放| 欧美日韩在线不卡一区| 欧美少妇一区| 国产区亚洲区欧美区| 国产在线成人| 亚洲国产日韩一级| 一区二区三区久久| 久久精品一级爱片| 欧美激情精品久久久久久蜜臀| 欧美激情一区二区三区成人| 亚洲无线一线二线三线区别av| 亚洲欧美一级二级三级| 久久人人爽人人爽| 国产精品久久久久影院亚瑟 | 欧美在线综合| 欧美粗暴jizz性欧美20| 一区二区高清| 久久久免费av| 国产精品九色蝌蚪自拍| 在线电影国产精品| 亚洲影院色无极综合| 久久综合网络一区二区| 99在线|亚洲一区二区| 久久黄金**| 国产精品久久久久久av下载红粉 | 久久久青草青青国产亚洲免观| 男人的天堂成人在线| 一本一本久久| 欧美国产精品人人做人人爱| 国产精品专区一| 99v久久综合狠狠综合久久| 久久精品一区中文字幕| a4yy欧美一区二区三区| 欧美一区日本一区韩国一区| 亚洲精品在线一区二区| 国产在线播放一区二区三区| 亚洲午夜精品| 91久久精品一区二区三区| 欧美一区二区在线播放| 欧美日韩中文精品| 日韩午夜av在线| 欧美激情第3页| 巨乳诱惑日韩免费av| 激情欧美一区| 久久亚洲精品一区| 久久精品盗摄| 国产综合久久久久影院| 久久精品99久久香蕉国产色戒| 一区二区三区四区五区在线| 欧美精品在线免费观看| 日韩视频中午一区| 亚洲欧洲日韩综合二区| 欧美激情成人在线视频| 91久久综合| 亚洲国产日韩精品| 欧美xxx成人| 亚洲激情网站免费观看| 欧美激情精品久久久久久变态| 久久综合激情| 亚洲欧洲免费视频| 亚洲三级色网| 国产精品久久97| 久久aⅴ乱码一区二区三区| 欧美一区二区三区精品电影| 韩国三级电影久久久久久| 美国十次了思思久久精品导航| 久久中文在线| 一区二区三区黄色| 亚洲欧美一级二级三级| 在线观看国产精品淫| 亚洲国产日韩美| 国产精品久久久久久一区二区三区| 欧美一级视频精品观看| 久久久久久久久久看片| 亚洲精品国产精品国自产观看浪潮| 亚洲三级网站| 国产日韩欧美一区二区| 免费成人高清在线视频| 欧美精品一区二区视频| 久久精品官网| 欧美黑人一区二区三区| 香蕉乱码成人久久天堂爱免费| 久久久久久穴| 亚洲欧美日韩中文视频| 久久手机免费观看| 亚洲一级在线观看| 久久久久久一区二区| 在线视频免费在线观看一区二区| 亚洲欧美成人| 日韩视频在线一区| 久久精品国产清高在天天线| 亚洲视频综合在线| 久久久久久噜噜噜久久久精品| 在线一区免费观看| 久久久av毛片精品| 亚洲自拍啪啪| 亚洲欧美福利一区二区| 久久久久综合| 欧美视频精品一区| 欧美国产欧美亚州国产日韩mv天天看完整 | 国产午夜精品一区理论片飘花| 欧美jizz19hd性欧美| 欧美天天综合网| 欧美大片专区| 国产一区再线| 亚洲一区二区在线免费观看视频| 亚洲国产人成综合网站| 欧美一区2区三区4区公司二百| 日韩亚洲不卡在线| 浪潮色综合久久天堂| 久久se精品一区精品二区| 欧美色中文字幕| 亚洲美女在线国产| 亚洲精品一区二区在线| 久久久精品国产免大香伊| 亚洲欧美日韩爽爽影院| 欧美丝袜一区二区| 日韩视频免费看| 一个人看的www久久| 欧美1区免费| 欧美国产亚洲精品久久久8v| 好吊色欧美一区二区三区视频| 午夜精品免费| 欧美有码视频| 国产欧美日韩亚州综合| 在线亚洲自拍| 亚洲欧美日韩精品久久久久| 欧美日韩国产免费观看| 亚洲欧洲精品成人久久奇米网| 在线成人h网| 毛片av中文字幕一区二区| 欧美va亚洲va日韩∨a综合色| 精品成人免费| 免费观看久久久4p| 亚洲国产乱码最新视频| 日韩一区二区久久| 欧美日韩在线一区二区| 一本一本久久a久久精品牛牛影视| 中国成人亚色综合网站| 国产精品国产三级国产专播精品人| 亚洲午夜视频| 久久在线免费观看| 91久久夜色精品国产网站| 欧美另类videos死尸| 国产精品99久久久久久宅男 | 亚洲精品欧美精品| 亚洲午夜久久久久久久久电影网| 欧美午夜性色大片在线观看| 亚洲视频导航| 久久综合电影一区| 亚洲精品视频一区| 国产精品第一区| 欧美在线观看一二区| 欧美福利视频一区| 在线亚洲电影| 国产一区二区三区在线观看免费| 久久夜色精品一区| 亚洲精品中文字幕女同| 欧美有码在线观看视频| 欧美夜福利tv在线| 99re亚洲国产精品| 欧美精品首页| 亚洲欧美综合v| 欧美韩国一区| 亚洲一区二区在线免费观看| 国产一级精品aaaaa看| 欧美1区视频| 午夜亚洲一区| 亚洲区免费影片| 久久国产欧美日韩精品| 亚洲欧洲免费视频| 国产亚洲精品7777| 欧美精品高清视频| 欧美在线一二三区| 一区二区高清视频在线观看| 免费成人黄色| 欧美一级播放| 艳妇臀荡乳欲伦亚洲一区| 国产揄拍国内精品对白| 国产精品超碰97尤物18| 久久久久国产精品麻豆ai换脸| 一本一道久久综合狠狠老精东影业| 另类图片综合电影| 欧美在线观看一区| 亚洲一区二区三区在线| 亚洲高清网站| 好吊成人免视频| 国产精品亚洲精品| 欧美日韩国产综合视频在线观看中文| 午夜视频一区在线观看| 在线亚洲精品福利网址导航| 亚洲国产成人在线视频| 久久亚洲私人国产精品va媚药| 亚洲欧美在线视频观看| 亚洲一区视频| 亚洲在线中文字幕| 亚洲一区二区三区国产| 一二美女精品欧洲|