解惑真小白的苦惱 | 類的物件,物件引用,物件例項,引用變數
對於剛接觸不久面向物件的真小白童鞋來說,類的物件,物件的例項,物件的引用,引用變數的問題以及莫過於沒得物件~雖然博主也沒得物件~,本文將逐個逐個講解!
1.何謂物件?
在Java中有一句比較流行的話,叫做“萬物皆物件”,這是Java語言設計之初的理念之一。要理解什麼是物件,需要跟類一起結合起來理解。下面這段話引自《Java程式設計思想》中的一段原話:
“按照通俗的說法,每個物件都是某個類(class)的一個例項(instance),這裡,‘類’就是‘型別’的同義詞。”
從這一句話就可以理解到物件的本質,簡而言之,它就是類的例項,比如所有的人統稱為“人類”,這裡的“人類”就是一個類(物種的一種型別),而具體到每個人,比如張三這個人,它就是物件,就是“人類”的例項。
2.何謂物件引用?
我們先看一段話,這段話同樣來自於《Java程式設計思想》:
“每種程式語言都有自己的資料處理方式。有些時候,程式設計師必須注意將要處理的資料是什麼型別。你是直接操縱元素,還是用某種基於特殊語法的間接表示(例如C/C++裡的指標)來操作物件。所有這些在
Java
裡都得到了簡化,一切都被視為物件。因此,我們可採用一種統一的語法。儘管將一切都“看作”物件,但操縱的識別符號實際是指向一個物件的“引用”(reference)。”
很顯然,從這段話可以看出物件和物件引用不是一回事,是兩個完全不同的概念。舉個例子,我們通常會用下面這一行程式碼來建立一個物件:
Person per = new Person("張三");
有小白童鞋會說,這裡的per
是一個物件,是Person
類的一個例項。也有小白童鞋會說,這裡的per
並不是真正的物件,而是指向所建立的物件的引用。到底哪種說法是對的?我們先不急著糾結哪種說法是對的,再看兩行程式碼:
Person person;
person = new Person("張三");
這兩行程式碼實現的功能和上面的一行程式碼是完全一樣的。大家都知道,在Java中new
是用來在堆上建立物件用的,如果per
是一個物件的話,那麼第二行為何還要通過new
來建立物件呢?
由此可見,per
並不是所建立的物件,是什麼?上面的一段話說的很清楚,“操縱的識別符號實際是指向一個物件的引用”,也就是說per
Person
類的物件的引用。真正建立物件的語句是右邊的new Person("張三")
;因此這裡的per
是一個引用,是指向一個可以指向Person
類的物件的引用。
簡單來說,物件的引用意思是“定義一個變數,這個變數指向的是一個物件“
Object obj=new Object();
//Object:類
//obj:物件的引用
//new Object():物件
3.何謂物件例項?
首先,沒有“物件的例項”這一說法,只有類的例項,而類的例項,指的就是類的物件,說白了就是物件。
但是還是有很多人這樣叫,那怎麼理解物件例項呢?比如說人類中有個叫宜春的程式設計師,宜春就是人類的一個例項
String s = new String("YiChun");
s
就是 String
類中的一個例項
關於物件例項官方沒有給其概念,其實有很多概念官方都沒有給的,什麼父類宣告指向子類物件、方法簽名等概念都是沒有的 ,只是人們經常這麼用這麼說就習慣了。因此關於例項物件大體可以理解為物件引用的意思...
4.何謂引用變數?
引用變數就是用引用型別宣告的變數,這種變數叫引用型別變數。如:
People people; //其中people就是引用變數,People是一個類屬於引用型別
5、物件與物件引用碰撞火花
從物件引用出發:
一個物件引用可以指向零個或一個物件
從物件出發:
一個物件可以被一個或多個物件引用
怎麼理解捏?~小白童鞋腦殼逐漸變大...~
5、1. 從物件引用出發:一個物件引用可以指向零個或一個物件
首先先來理解第一句話:從物件引用出發:一個物件引用可以指向零個或一個物件
public static void main(String[] args) {
Two t; //一個物件引用可以指向零個物件
t=new Two();//一個物件引用可以指向一個物件
t=new String();//一個物件引用不可以指向 >1個物件
}
試想一下這樣的程式碼會出現啥情況?是的,它會編譯失敗
看完上面這個例子就能說明了麼?我們接著看下面這個程式碼:
public static void main(String[] args) {
String str;
str=new String("string1");
str=new String("string2");
}
我們知道,凡是new
都能創建出一個物件,我們發現上面程式碼String
物件引用str
一個new
了兩次,而且上面程式碼編譯也不報錯,的的確確是建立了兩個物件,那這怎麼說?小白童鞋說完感覺把博主按在馬桶蓋上...
別急,我們再看看上面程式碼輸出啥
public static void main(String[] args) {
String str;
str=new String("string1");
str=new String("string2");
System.out.println(str);
}
執行結果: string2
這說明啥?說明現在str是下一個物件的引用。上一個物件被垃圾回收了,因為上一個物件(也就是string1
)不能被再次使用了。因此上面這個程式可以這樣理解:
public static void main(String[] args) {
String str;//一個物件引用str指向零個物件
str=new String("string1");//一個物件引用str指向一個物件string1
str=new String("string2");//注意:這裡物件引用str並不是指向第二個物件string2,而是將之前指向第一個物件string1的引用重新指向了另一個物件string2
}
物件引用str並不是指向第二個物件string2,而是將之前指向第一個物件string1的引用重新指向了另一個物件string2,因此從物件引用出發:一個物件引用可以指向零個或一個物件!
這個時候,小白童鞋漸漸鬆開了把博主按在馬桶蓋上的雙手...
5、2. 從物件出發:一個物件可以被一個或多個物件引用
我們再來理解一下第二句話:從物件出發,一個物件可以被一個或多個物件引用
小白童鞋同樣不解,於是又用雙手把博主按在馬桶蓋上...
看下面這個程式:
Demo demo1,demo2,demo3;
demo1=new Demo();
demo2=demo1;
demo3=demo2;
怎麼理解?看的有點暈?會不會感覺後面兩句程式碼就是物件引用=物件引用...
其實要弄清除這個,首先你得弄清楚java虛擬機器記憶體,弄清楚變數(物件引用)和物件是如何儲存的,物件引用是儲存在棧記憶體中,而物件是儲存在堆記憶體中。分析如下:
Demo demo1,demo2,demo3;//建立多個物件引用,都儲存在棧中
demo1=new Demo();//建立一個Demo物件,儲存在堆中,並將demo1指向這個物件,相當於加了一個鏈
demo2=demo1;//demo2與demo1一樣,都指向堆中Demo物件
demo3=demo2;//demo3與demo2一樣,都指向堆中Demo物件
首先,每個物件只有一個地址值,new Demo()
是建立了一個物件,demo1
是這個物件的地址值,用來找到這個物件,demo2=demo1
是把new Demo()
這個物件的地址值由demo1
改為了demo2
,後面的demo3=demo2
也是隻改變了物件的地址值,物件本身的空間大小都沒有變化,變的,是這個物件的地址值,也就是c裡面所謂的指標。
這個時候,小白童鞋漸漸鬆開了把博主按在馬桶蓋上的雙手...
最後,我們再看看一個網上關於物件與物件引用很流行的程式與分析,程式碼如下:
UserType ut = new UserType(); // ut是引用,實際的物件在記憶體裡。
ut = new UserType(); /*現在ut是另一個物件的引用,先前的物件被垃圾回收了(因為先前的物件不能被再次使用了)。*/
UserType ut2; // 定義了一個引用ut2,他不引用任何物件,不能使用。。。。
ut2 = new UserType(); // 然ut2成為一個物件的引用。
UserType ut3 = new UserType();
UserType ut4 = new UserType();
ut3 = ut4; // 現在ut3引用ut4的物件,這裡不是賦值。。。
int a = 5;
int b = 4;
a = b; // 這裡是賦值。 a b 依然引用不同的物件
6、最後要相信的真理
對於面嚮物件語言,如java,首先,請小白童鞋相信一句話:一切皆為物件。然後相信另一句話:變數只是一個零時的儲存地點。引用型別的變數只是一個普通變數,儲存了引用型別的地址。物件的建立是直接在記憶體中分配一個記憶體。
最後再梳理一下
引用型別變數 就 相當於 電腦上的快捷方式; 物件就相當於 你 磁盤裡面 安裝的遊戲,它 實實在在 佔用你的空間記憶體; 而變數 只是快捷方式
說白了基本資料型別變數就像是直接放在櫃子裡的東西,而引用資料型別變數就是這個櫃子對應編碼的鑰匙。鑰匙號和櫃子對應。
到這裡文章就結束了喔,小白童鞋,你何識著咩啊~
最後,若有不足或者不正之處,歡迎指正批評,感激不盡!
歡迎各位關注我的公眾號,一起探討技術,嚮往技術,追求技術...
小白童鞋關注了我的公眾號之後,又用雙手把博主按在馬桶蓋蓋上.