• <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>

            天之道

            享受編程的樂趣。
            posts - 118, comments - 7, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            Java對象引用(轉)

            Posted on 2013-09-27 08:39 hoshelly 閱讀(567) 評論(0)  編輯 收藏 引用 所屬分類: Java
            作者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!

             

            我們之前一直在使用“對象”這個概念,但沒有探討對象在內存中的具體存儲方式。這方面的討論將引出“對象引用”(object reference)這一重要概念。 

             

            對象引用
            我們沿用之前定義的Human類,并有一個Test類:

            復制代碼
            public class Test
            {
                public static void main(String[] args)
                {
                    Human aPerson = new Human(160);                 
                }
            }

            class Human
            {   
                /**
                 * constructor
                 */
                public Human(int h)
                {
                    this.height = h;
                }

                /**
                 * accessor
                 */
                public int getHeight()
                {
                   return this.height;
                }

                /**
                 * mutator
                 */
                public void growHeight(int h)
                {
                    this.height = this.height + h;
                }

                private int height;
            }
            復制代碼
             

            外部可以調用類來創建對象,比如上面在Test類中:

            Human aPerson = new Human(160);
            創建了一個Human類的對象aPerson。 

            上面是一個非常簡單的表述,但我們有許多細節需要深入:

            首先看等號的右側。new是在內存中為對象開辟空間。具體來說,new是在內存的堆(heap)上為對象開辟空間。這一空間中,保存有對象的數據和方法。
            再看等號的左側。aPerson指代一個Human對象,被稱為對象引用(reference)。實際上,aPerson并不是對象本身,而是類似于一個指向對象的指針。aPerson存在于內存的棧(stack)中。
            當我們用等號賦值時,是將右側new在堆中創建對象的地址賦予給對象引用。
            這里的內存,指的是JVM (Java Virtual Machine)虛擬出來的Java進程內存空間。內存的堆和棧概念可參考Linux從程序到進程。

             



            對象引用


            棧的讀取速度比堆快,但棧上存儲的數據受到有效范圍的限制。在C語言中,當一次函數調用結束時,相應的棧幀(stack frame)要刪除,棧幀上存儲的參量和自動變量就消失了。Java的棧也受到同樣的限制,當一次方法調用結束,該方法存儲在棧上的數據將清空。在 Java中,所有的(普通)對象都儲存在堆上。因此,new關鍵字的完整含義是,在堆上創建對象。

             

            基本類型(primitive type)的對象,比如int, double,保存在棧上。當我們聲明基本類型時,不需要new。一旦聲明,Java將在棧上直接存儲基本類型的數據。所以,基本類型的變量名表示的是數據本身,不是引用。

             

             

            引用和對象的關系就像風箏和人。我們看天空時(程序里寫的),看到的是風箏(引用),但風箏下面對應的,是人(對象):



            引用和對象分離;引用指向對象

             

            盡管引用和對象是分離的,但我們所有通往對象的訪問必須經過引用這個“大門”,比如以 引用.方法() 的方式訪問對象的方法。在Java中,我們不能跳過引用去直接接觸對象。再比如,對象a的數據成員如果是一個普通對象b,a的數據成員保存的是指向對象b的引用 (如果是基本類型變量,那么a的數據成員保存的是基本類型變量本身了)。

            在Java中,引用起到了指針的作用,但我們不能直接修改指針的值,比如像C語言那樣將指針值加1。我們只能通過引用執行對對象的操作。這樣的設計避免了許多指針可能引起的錯誤。

             

            引用的賦值
            當我們將一個引用賦值給另一個引用時,我們實際上復制的是對象的地址。兩個引用將指向同一對象。比如 dummyPerson=aPerson;,將導致:



            一個對象可以有多個引用 (一個人可以放多個風箏)。當程序通過某個引用修改對象時,通過其他引用也可以看到該修改。我們可以用以下Test類來測試實際效果:

            復制代碼
            public class Test
            {
                public static void main(String[] args)
                    {
                         Human aPerson = new Human(160);
                         Human dummyPerson = aPerson;
                         System.out.println(dummyPerson.getHeight());
                         aPerson.growHeight(20);
                         System.out.println(dummyPerson.getHeight());
                    }
            }
            復制代碼
            我們對aPerson的修改將影響到dummyPerson。這兩個引用實際上指向同一對象。

             

            所以,將一個引用賦值給另一個引用,并不能復制對象本身。我們必須尋求其他的機制來復制對象。

             

            垃圾回收
            隨著方法調用的結束,引用和基本類型變量會被清空。由于對象存活于堆,所以對象所占據的內存不會隨著方法調用的結束而清空。進程空間可能很快被不斷創建的對象占滿。Java內建有垃圾回收(garbage collection)機制,用于清空不再使用的對象,以回收內存空間。

            垃圾回收的基本原則是,當存在引用指向某個對象時,那么該對象不會被回收; 當沒有任何引用指向某個對象時,該對象被清空。它所占據的空間被回收。

            上圖假設了某個時刻JVM中的內存狀態。Human Object有三個引用: 來自棧的aPerson和dummyPerson,以及另一個對象的數據成員president。而Club Object沒有引用。如果這個時候垃圾回收啟動,那么Club Object將被清空,而Human Object來自Club Object的引用(president)也隨之被刪除。

             

            垃圾回收是Java中重要的機制,它直接影響了Java的運行效率。我將在以后深入其細節。

             

            參數傳遞

            當我們分離了引用和對象的概念后,Java方法的參數傳遞機制實際上非常清晰: Java的參數傳遞為值傳遞。也就是說,當我們傳遞一個參數時,方法將獲得該參數的一個拷貝。

            實際上,我們傳遞的參數,一個是基本類型的變量,另一個為對象的引用。

            基本類型變量的值傳遞,意味著變量本身被復制,并傳遞給Java方法。Java方法對變量的修改不會影響到原變量。

            引用的值傳遞,意味著對象的地址被復制,并傳遞給Java方法。Java方法根據該引用的訪問將會影響對象。

             

            在這里有另一個值得一提的情況: 我們在方法內部使用new創建對象,并將該對象的引用返回。如果該返回被一個引用接收,由于對象的引用不為0,對象依然存在,不會被垃圾回收。

             

            總結
            new

            引用,對象

            被垃圾回收的條件

            參數: 值傳遞

             
            国产精品久久久久久影院| 欧美久久综合九色综合| 亚洲va中文字幕无码久久不卡| 伊人久久成人成综合网222| 偷窥少妇久久久久久久久| 性欧美丰满熟妇XXXX性久久久 | 国产成人综合久久精品红| 国内精品综合久久久40p| 国产精品99久久久久久宅男| 国产高潮国产高潮久久久91| 偷偷做久久久久网站| 99久久免费国产精品热| 97香蕉久久夜色精品国产| 久久婷婷国产麻豆91天堂| 亚洲色欲久久久久综合网| 欧美亚洲国产精品久久蜜芽| 97精品依人久久久大香线蕉97 | 国产精品久久久久久久久久影院 | 久久国产乱子伦精品免费午夜| 老男人久久青草av高清| 久久精品国产福利国产琪琪| 亚洲av伊人久久综合密臀性色| 久久久久综合中文字幕| 91精品国产综合久久香蕉| 久久久久久国产精品无码超碰| 久久久久久毛片免费看| 精品久久久久久| 成人综合伊人五月婷久久| 久久婷婷国产综合精品| 一级女性全黄久久生活片免费| 中文字幕一区二区三区久久网站| 亚洲第一极品精品无码久久| 欧美日韩精品久久免费| 人人狠狠综合久久亚洲高清| 久久er国产精品免费观看8| 久久亚洲国产精品一区二区| 欧美噜噜久久久XXX| 欧洲人妻丰满av无码久久不卡| 久久AV高潮AV无码AV| 亚洲国产美女精品久久久久∴ | 99久久精品免费看国产|