對於剛接觸不久面向對象的真小白童鞋來說,類的對象,對象的實例,對象的引用,引用變量的問題以及莫過於沒得對象雖然博主也沒得對象,本文將逐個逐個講解!
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,首先,請小白童鞋相信一句話:一切皆為對象。然后相信另一句話:變量只是一個零時的儲存地點。引用類型的變量只是一個普通變量,儲存了引用類型的地址。對象的創建是直接在內存中分配一個內存。
最后再梳理一下
引用類型變量 就 相當於 電腦上的快捷方式; 對象就相當於 你 磁盤里面 安裝的游戲,它 實實在在 占用你的空間內存; 而變量 只是快捷方式
說白了基本數據類型變量就像是直接放在櫃子里的東西,而引用數據類型變量就是這個櫃子對應編碼的鑰匙。鑰匙號和櫃子對應。
到這里文章就結束了喔,小白童鞋,你何識着咩啊~
最后,若有不足或者不正之處,歡迎指正批評,感激不盡!
歡迎各位關注我的公眾號,一起探討技術,向往技術,追求技術...
小白童鞋關注了我的公眾號之后,又用雙手把博主按在馬桶蓋蓋上....