乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      java 傳值 vs. 傳引用

       pstn 2007-11-22

      java 傳值 vs. 傳引用

      java程序的函數(shù)調(diào)用到底是傳值呢還是傳參呢?這可是個(gè)難纏的問題,如果搞不清楚還是挺容易出錯(cuò)的:P對(duì)于這個(gè)問題,最經(jīng)典的解釋莫過于“java函數(shù)是傳值的,java函數(shù)傳遞的參數(shù)是對(duì)象的引用”
      這兩句話好像初聽上去有點(diǎn)繞,不過意思倒是表達(dá)得蠻精確的。
      我看到過幾個(gè)解釋這個(gè)問題的例子,不過個(gè)人感覺看過例子之后還是只知道是什么不知道為什么,停留在照貓畫虎的水平上還是挺容易出問題的。所以舉例子之前,先從jvm的實(shí)現(xiàn)原理上有個(gè)了解應(yīng)當(dāng)是不無裨益的。jvm的結(jié)構(gòu)圖前一陣子貼到blog上了,那可是從“深入java虛擬機(jī)”這本巨牛的書上看來的,絕對(duì)有權(quán)威性。從jvm的結(jié)構(gòu)圖上可以看出來,jvm在實(shí)現(xiàn)的時(shí)候?qū)儆谒膬?nèi)存分為五部分,其中程序代碼(嚴(yán)格的說應(yīng)當(dāng)是字節(jié)碼)是放在java棧的棧幀中,而對(duì)象是從堆中分配的,堆這個(gè)東西我看可以理解成“對(duì)象池”。程序和程序中需要用到的對(duì)象放在兩個(gè)相對(duì)獨(dú)立的區(qū)域中,那么程序怎么使用對(duì)象呢?答案是程序中真正使用對(duì)象的地方其實(shí)只是聲明了一個(gè)對(duì)象的引用,也就是把堆中分配了的相應(yīng)對(duì)象的地址放到引用中,棧和堆之間就是通過一個(gè)一個(gè)的引用來聯(lián)系的。引用嘛,我理解就是一個(gè)指針常量,指針常量又是個(gè)什么東西呢?說白了,就是一個(gè)無符號(hào)整數(shù),這個(gè)整數(shù)所表達(dá)的是引用對(duì)象的地址。好了,這下清楚了,不管是基本類型變量(int,float,double什么的)還是對(duì)象,相應(yīng)的內(nèi)存地址中存放的都是一個(gè)數(shù)(無符號(hào)整數(shù),整數(shù),浮點(diǎn)數(shù)等)。傳遞參數(shù)的時(shí)候傳遞的就是相應(yīng)內(nèi)存地址中的數(shù),所以說“java函數(shù)是傳值的”。當(dāng)然,這個(gè)數(shù)對(duì)于基本類型和對(duì)象類型來說意義是不一樣的,對(duì)于基本類型這個(gè)數(shù)就是其值本身,傳遞值的結(jié)果就是,改變新的變量的值不影響舊的變量的值;而對(duì)于對(duì)象來說這個(gè)數(shù)是它的地址,傳遞這個(gè)值就相當(dāng)于傳遞了真實(shí)對(duì)象的引用,傳遞了引用或者說是地址的結(jié)果就是變化會(huì)全局可見,所以又可以說“java函數(shù)傳遞的參數(shù)是對(duì)象的引用”。
      唔,松口氣啦。經(jīng)過上面這一小堆討論,不難理解為什么java在傳遞參數(shù)時(shí)對(duì)于基本類型和對(duì)象表現(xiàn)不同:)
      現(xiàn)在開始舉例了,舉網(wǎng)上搜來的例子,看看是不是比原來沒有上面的解釋的時(shí)候好理解一點(diǎn)?
      public class TestRef
      {
       public static void main(String[] args)
       {
        ValueObject vo1 = new ValueObject("A", 1);
        System.out.println("after vo1: " + vo1.getName()); //=A
       
        changeValue1(vo1);
        System.out.println("after changeValue1: " + vo1.getName());
                      //=A1, changed
       
        changeValue2(vo1);
        System.out.println("after changeValue2: " + vo1.getName());
                      //=A1, changeValue2內(nèi)部的賦值不會(huì)影響這里。
       }
       /**
        * 使用vo1自身的函數(shù)對(duì)其內(nèi)部數(shù)據(jù)進(jìn)行改變是有效的,函數(shù)外可反映出來,
        * 因?yàn)檫@是對(duì)對(duì)象本身的操作
        * 這種object稱為可變的(mutable)
        * @param vo1
        */
       private static void changeValue1(ValueObject vo1)
       {
        vo1.setName("A1");
       }
       /**
        * 在函數(shù)內(nèi)給vo1重新賦值不會(huì)改變函數(shù)外的原始值,因?yàn)檫@種改變了引用的指向
        * @param vo1
        */
       private static void changeValue2(ValueObject vo1)
       {
        vo1 = new ValueObject("B", 2);
        System.out.println("inside changeValue2: "+ vo1.getName());
                      //=B,賦值操作引起的結(jié)果變化僅在changeValue2內(nèi)部有效
       }
      }
      class ValueObject
      {
       
       public ValueObject() {}
       
       public ValueObject(String name, int id)
       {
        this.name = name;
        this.id = id;
       }
       
       private String name;
       private int id;
       public int getId() {
        return id;
       }
       public void setId(int id) {
        this.id = id;
       }
       public String getName() {
        return name;
       }
       public void setName(String name) {
        this.name = name;
       }
      }
      java中對(duì)象的每個(gè)實(shí)例(就是對(duì)象)內(nèi)存地址是唯一的,它一旦被創(chuàng)建,能夠?qū)@個(gè)地址進(jìn)行操作的就是其本身,如果ValueObject類中沒有public void setName之類的方法對(duì)這個(gè)類的實(shí)例中的數(shù)據(jù)進(jìn)行修改的話,程序是沒有任何別的方法可以修改ValueObject類的實(shí)例中的數(shù)據(jù),這個(gè)就是java的封裝特性。對(duì)于不提供修改內(nèi)部數(shù)據(jù)的方法的類,我們稱為不可變(immutable)的類。在函數(shù)中對(duì)傳入的參數(shù)變量進(jìn)行賦值操作,只能在函數(shù)范圍內(nèi)改變局部變量指向的引用地址,但是不會(huì)改變?cè)嫉刂返膬?nèi)容。因此,在changeValue2(...)函數(shù)內(nèi)部的vo1和函數(shù)外的vo1雖然名字相同,但是實(shí)際上是不同的實(shí)例變量,只不過指向了和函數(shù)外的vo1同樣的地址,所以當(dāng)我們用vo1=... 對(duì)其進(jìn)行賦值的時(shí)候,只不過是把函數(shù)內(nèi)的臨時(shí)變量指向了新的地址,并沒有改變?cè)紇o1內(nèi)存地址中的內(nèi)容。這就是在運(yùn)行changeValue2(...)之后,vo1的值在main范圍內(nèi)仍然沒有被修改的原因。而changeValue1里面是調(diào)用的ValueObject本身的function來更改其內(nèi)容,因此是原始內(nèi)存地址中的數(shù)據(jù)被更改了,所以是全局有效的.
      總結(jié):
      對(duì)于引用類型的傳參也是傳值的,傳的是引用類型的值,其實(shí)就是對(duì)象的地址。
      1. java參數(shù)傳遞值的。
      2. java所有對(duì)像變量都是對(duì)像的引用。
      不知道我解釋清楚沒,要是還是不能理解java參數(shù)傳遞的原理,強(qiáng)烈推薦看看“深入java虛擬機(jī)”一書的第五章,中文翻譯的不是特別出色,可以看看英文原版,應(yīng)該比中文版好懂:)

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多