深入理解類、物件、引用三者之間的關係
本文旨在掃盲,深入理解類、物件、引用三者之間的關係,在處理 a = b = c 這類問題上可以有清晰無誤的思考。
一、什麼是類
類是一個模板,它描述一類物件的行為和狀態。
拿一條狗來舉例,它的狀態有:名字、品種、顏色,行為有:叫、搖尾巴和跑。
說白了,類就是我們自然界的一些統稱,比如人、狗、車等。我們已經在實際生活中,將一些事物主動劃分為某一類,將這個概念延伸至軟體開發中,就是我們自己所寫的 class 檔案。
具體將哪些事物劃分為某一類是由我們自己去調節的。比如,你可以將狗劃分為一類,但是狗中的杜賓犬也可以成為一類。舉個例子,一家專門出售杜賓犬的商店可以對所有的杜賓犬進行編號,記錄每個杜賓犬的姓名、飲食時間。
二、什麼是物件
物件是類的一個例項,具有狀態和行為。
如果說類是指的某一類,那麼物件就是這一類當中具體的一個事物。比如狗,具體起來又分為拉布拉多、哈士奇,巴哥犬、吉娃娃等。它們都有自己獨特的狀態:名字、品種、顏色,以及獨特的行為:叫、搖尾巴和跑。
對比現實物件和軟體物件,它們之間十分相似。
軟體物件也有狀態和行為。軟體物件的狀態就是屬性,行為通過方法體現。
在軟體開發中,方法操作物件內部狀態的改變,物件的相互呼叫也是通過方法來完成。
三、類與物件
類是我們所寫的 class 檔案,抽象出了一系列狀態和行為,是我們例項化具體物件的模板。
比如我們有一個類(Dog.class),程式碼如下:
public class Dog{ String breed; int age; String color; void barking(){ } void hungry(){ } void sleeping(){ }
在Java中,使用關鍵字new來建立一個新的物件。
new Dog();
通過 new 關鍵字,我們完成了由抽象類例項化具體物件的步驟。並且在記憶體空間,多了一塊儲存該例項物件的區域。如圖一所示:
四、物件與引用
物件已經 new 出來了,我們如何發出指令來呼叫物件自身的屬性和方法呢?
還需要一個引用(reference)來幫我們實現發出指令的操作。
Java中引用的程式碼宣告如下:
Dog dog;
更清晰的理解可以用圖二表示如下:
使用等號(=)將引用與物件進行連結,程式碼如下:
Dog dog = new Dog();
更清晰的理解用圖三表示如下:
物件與引用的關係是一對多的關係,一個物件可以被多個多個引用連結。如圖四所示:
由引用實現發出指令的操作,指令的執行是由物件自身完成的。比如下面這段程式碼:
Dog dog = new Dog();
dog.sleeping()
在記憶體空間中的執行原理如圖五所示:
引用 dog 發出執行 sleeping() 方法的指令,具體的執行完全是由記憶體中的 Dog 物件來完成的。
五、引用傳遞
對於上述中的引用指向物件,執行的過程已經清晰明瞭,那麼對於引用指向引用的情況又該如何去做呢?比如下面這段Java程式碼:
Dog dog1 = new Dog();
Dog dog2 = dog1;
dog1 = null;
dog2.sleeping()
此時執行程式碼的最後一行究竟會不會報錯呢?答案是不會。
因為引用A指向引用B,實際上是指向引用B指向的記憶體空間,並不是指向引用本身。
上述程式碼用圖六表示如下:
引用可以理解為沒有空間的存在,只要使用引用就必須對其初始化賦值(可為 NULL)。
在C語言的世界裡,沒有引用,只有指標。在Java的世界裡,沒有指標,只有引用。實際上,Java裡的引用就是C裡的指標,只是Java把這個指標封裝了起來,避免進行繁瑣的指標操作。
六、課後練習
不執行程式碼,你可以分析出這段Java程式碼的執行邏輯嗎?(推薦使用上面圖片的形式進行畫圖分析)
public class Node {
Node prev;
Node next;
int id;
public Node(int id) {
this.id = id;
}
public static void main(String[] args) {
Node e = new Node(1);
e.next = new Node(2);
e.next.next = new Node(3);
Node hd = null, tl = null;
do {
Node p = new Node(e.id);
if (tl == null)
hd = p;
else {
p.prev = tl;
tl.next = p;
}
tl = p;
} while ((e = e.next) != null);
Node n = hd;
do {
System.out.println(n.id);
}while ((n = n.next)!=null);
}
}