1. 程式人生 > >深入理解類、物件、引用三者之間的關係

深入理解類、物件、引用三者之間的關係

本文旨在掃盲,深入理解類、物件、引用三者之間的關係,在處理 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);
    }
}