Java中对象和引用的理解
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
偶然想起Java中對象和引用的基本概念,為了加深下對此的理解和認識,特地整理一下相關(guān)的知識點,通過具體實例從兩者的概念和區(qū)別兩方面去更形象的認識理解,再去記憶。- 1
- 2
一、對象和引用的概念:?
在Java中萬物皆對象,比如我們定義一個簡單的動物類:
- 1
- 2
- 3
- 4
- 5
有了這個Animal類之后,我們可以來創(chuàng)建一個Animal對象:
Animal an = new Animal();- 1
我們把編寫這個語句的動作就稱作創(chuàng)建一個對象,細化這個動作為:?
1. 右面的”new Animal”,是以Animal類為模板的,在堆空間里創(chuàng)建一個Animal對象;?
2. 末尾的”( )”代表著:在對象創(chuàng)建之后,立即調(diào)用Animal類的構(gòu)造函數(shù),對新生成的對象進行初始化。(如果沒構(gòu)造函數(shù),Java會有一個默認的構(gòu)造函數(shù)的);?
3. 左面的”Animal an” 創(chuàng)建了一個Animal類引用變量。即以后可以用來指向Animal對象的對象引用;?
4. “=” 操作符使對象引用指向剛才創(chuàng)建的那個Animal對象。?
拆分開也就是:等同于
- 1
- 2
有兩個實體:一個是對象引用變量;一個是對象本身。?
在java中,都是通過引用來操縱對象的,這也是兩者的區(qū)別。
二、對象和引用的區(qū)別:?
1、關(guān)聯(lián)性:?
1). 當對象的引用變量指向?qū)ο髸r,兩者就互相聯(lián)系起來,改變引用的屬性,就會改變對象的屬性;?
2). 如果同一個對象被多個引用變量引用的話,則這些引用變量將共同影響這個對象本身;?
3). 在java中,都是通過引用來操縱對象的。
2、差異性:?
1). 一個對象可以被不同的引用變量來操縱,同時一個引用變量也可以指向不同的對象,但是同一時刻下只能指向一個對象。?
2). 從存儲空間上來看,對象和引用也是相互獨立的,對象一般存儲在堆中,而引用存儲在堆棧中(存儲速度而更快)。
對于引用變量的深層含義,未必在初學(xué)的時候就能深刻理解,?
所以理解好下面這兩句話的真正含義非常重要
- 1
- 2
- 3
- 4
- 5
1.先搞清楚什么是堆,什么是棧。?
Java開辟了兩類存儲區(qū)域,對比二者的特點
| 棧 | 基本類型的變量和對象的引用變量 | 存取速度比堆要快,僅次于寄存器,棧數(shù)據(jù)可以共享 | 存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性。棧中主要存放一些基本類型的變量 | 當超過變量的作用域后,Java會自動釋放掉該變量,內(nèi)存空間可以立即被另作他用 |
| 堆 | 由new等指令創(chuàng)建的對象和數(shù)組 | 可以動態(tài)地分配內(nèi)存大小,生存期也不必事先告訴編譯器 | 由于要在運行時動態(tài)分配內(nèi)存,存取速度較慢 | 由Java虛擬機的自動垃圾回收器來回收不再使用的數(shù)據(jù) |
堆棧的存儲特點決定了其中存儲的數(shù)據(jù)類型。
注意,棧內(nèi)存儲的除了基本類型的變量(String, int 這種類型的變量)還會存儲對象的引用變量。java中,引用變量實際上是一個指針,它指向的是堆內(nèi)存中對象實例。
引用變量就相當于是為數(shù)組或?qū)ο笃鸬囊粋€名稱,以后就可以在程序中使用棧中的引用變量來訪問堆中的數(shù)組或?qū)ο蟆?/p>
2.給引用變量賦值
回過頭再來看代碼
實際上里面分解成了四個步驟。
Case cc; '''在棧內(nèi)存里面開辟了空間給引用變量cc,這時cc=null''' cc=new Case(); ''' 1. new Case()在堆內(nèi)存里面開辟了空間給Case類的對象,這個對象沒有名字 2. Case()隨即調(diào)用了Case類的構(gòu)造函數(shù) 3. 把對象的地址在堆內(nèi)存的地址給引用變量cc '''- 1
- 2
- 3
- 4
- 5
- 6
- 7
這樣我們就明確了:
- Java中,這里的“=”并不是賦值的意思,而是把對象的地址傳遞給變量;
- 對象創(chuàng)建出來,其實連名字都沒有,因此必須通過引用變量來對其進行操作。
為了形象地說明對象、引用及它們之間的關(guān)系,可以做一個或許不很妥當?shù)谋扔鳌ο蠛帽仁且恢缓艽蟮臍馇?#xff0c;大到我們抓不住它。引用變量是一根繩, 可以用來系汽球
緊接著就會問,引用變量是怎么傳遞的呢??
這就涉及到Java唯一的參數(shù)傳遞方式——按值傳遞
看下面一段代碼:
public class ObjectRef {'''基本類型的參數(shù)傳遞'''public static void testBasicType(int m) {System.out.println("m=" + m);//m=50m = 100;System.out.println("m=" + m);//m=100}'''參數(shù)為對象,不改變引用的值''''''s即sMain指向的對象執(zhí)行了append方法,在原來的字符串上加了段“_add”'''public static void add(StringBuffer s) {s.append("_add");}'''參數(shù)為對象,改變引用的值 ''''''引用變量指向了一個新的對象,已經(jīng)不是sMain指向的對象了'''public static void changeRef(StringBuffer s) {s = new StringBuffer("Java");}public static void main(String[] args) {int i = 50;testBasicType(i);System.out.println(i);'''i=50'''StringBuffer sMain = new StringBuffer("init");System.out.println("sMain=" + sMain.toString());'''sMain=init'''add(sMain);System.out.println("sMain=" + sMain.toString());'''sMain=init_add'''changeRef(sMain);System.out.println("sMain=" + sMain.toString());'''sMain=Java'''} }看這里,給人的感覺是傳遞過來的明明是對象的引用,為什么就是值得傳遞呢??
因為傳遞之前,被傳的就是個引用啊,我們所謂的“傳地址”,在傳之前,那可是一個實例,傳過來的是實例的地址。這里傳遞的值,從始至終就是個地址,sMain就是個地址,傳給s還是個地址。你們感受下:
以上輸出的結(jié)果會是“init_add”
而這里,s引用了一個新的對象,根本沒有進行參數(shù)的傳遞,它和之前的sMain沒有關(guān)系了。
'''參數(shù)為對象,改變引用的值 ''' '''引用變量指向了一個新的對象,已經(jīng)不是sMain指向的對象了'''public static void changeRef(StringBuffer s) {s = new StringBuffer("Java");}以上輸出的結(jié)果會是“Java”?
.?
.?
引用《Java編程思想》中的一段話:
倘若“將一個對象賦值給另一個對象”,實際是將“引用”從一個地方復(fù)制到另一個地方:
轉(zhuǎn)載于:https://my.oschina.net/architectliuyuanyuan/blog/1630113
總結(jié)
以上是生活随笔為你收集整理的Java中对象和引用的理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 特斯拉股价暴跌,疯狂烧钱是否真的能够带来
- 下一篇: java嵌入groovy脚本_Java封